Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(8)

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLSelectElement.cpp

Issue 2572953002: SELECT element: Do not update popup menu content by touching selectedIndex (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLSelectElement.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). 2 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 3 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
4 * (C) 1999 Antti Koivisto (koivisto@kde.org) 4 * (C) 1999 Antti Koivisto (koivisto@kde.org)
5 * (C) 2001 Dirk Mueller (mueller@kde.org) 5 * (C) 2001 Dirk Mueller (mueller@kde.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights 6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights
7 * reserved. 7 * reserved.
8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) 8 * (C) 2006 Alexey Proskuryakov (ap@nypop.com)
9 * Copyright (C) 2010 Google Inc. All rights reserved. 9 * Copyright (C) 2010 Google Inc. All rights reserved.
10 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. 10 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved.
(...skipping 963 matching lines...) Expand 10 before | Expand all | Expand 10 after
974 setRecalcListItems(); 974 setRecalcListItems();
975 m_lastOnChangeSelection.clear(); 975 m_lastOnChangeSelection.clear();
976 } 976 }
977 977
978 // TODO(tkent): This function is not efficient. It contains multiple O(N) 978 // TODO(tkent): This function is not efficient. It contains multiple O(N)
979 // operations. crbug.com/577989. 979 // operations. crbug.com/577989.
980 void HTMLSelectElement::selectOption(HTMLOptionElement* element, 980 void HTMLSelectElement::selectOption(HTMLOptionElement* element,
981 SelectOptionFlags flags) { 981 SelectOptionFlags flags) {
982 TRACE_EVENT0("blink", "HTMLSelectElement::selectOption"); 982 TRACE_EVENT0("blink", "HTMLSelectElement::selectOption");
983 983
984 bool shouldUpdatePopup = false;
985
984 // selectedOption() is O(N). 986 // selectedOption() is O(N).
985 if (isAutofilled() && selectedOption() != element) 987 if (isAutofilled() && selectedOption() != element)
986 setAutofilled(false); 988 setAutofilled(false);
987 989
988 if (element) { 990 if (element) {
991 if (!element->selected())
992 shouldUpdatePopup = true;
989 element->setSelectedState(true); 993 element->setSelectedState(true);
990 if (flags & MakeOptionDirty) 994 if (flags & MakeOptionDirty)
991 element->setDirty(true); 995 element->setDirty(true);
992 } 996 }
993 997
994 // deselectItemsWithoutValidation() is O(N). 998 // deselectItemsWithoutValidation() is O(N).
995 if (flags & DeselectOtherOptions) 999 if (flags & DeselectOtherOptions)
996 deselectItemsWithoutValidation(element); 1000 shouldUpdatePopup |= deselectItemsWithoutValidation(element);
997 1001
998 // We should update active selection after finishing OPTION state change 1002 // We should update active selection after finishing OPTION state change
999 // because setActiveSelectionAnchorIndex() stores OPTION's selection state. 1003 // because setActiveSelectionAnchorIndex() stores OPTION's selection state.
1000 if (element) { 1004 if (element) {
1001 // setActiveSelectionAnchor is O(N). 1005 // setActiveSelectionAnchor is O(N).
1002 if (!m_activeSelectionAnchor || !isMultiple() || 1006 if (!m_activeSelectionAnchor || !isMultiple() ||
1003 flags & DeselectOtherOptions) 1007 flags & DeselectOtherOptions)
1004 setActiveSelectionAnchor(element); 1008 setActiveSelectionAnchor(element);
1005 if (!m_activeSelectionEnd || !isMultiple() || flags & DeselectOtherOptions) 1009 if (!m_activeSelectionEnd || !isMultiple() || flags & DeselectOtherOptions)
1006 setActiveSelectionEnd(element); 1010 setActiveSelectionEnd(element);
1007 } 1011 }
1008 1012
1009 // Need to update m_lastOnChangeOption before 1013 // Need to update m_lastOnChangeOption before
1010 // LayoutMenuList::updateFromElement. 1014 // LayoutMenuList::updateFromElement.
1011 bool shouldDispatchEvents = false; 1015 bool shouldDispatchEvents = false;
1012 if (usesMenuList()) { 1016 if (usesMenuList()) {
1013 shouldDispatchEvents = (flags & DispatchInputAndChangeEvent) && 1017 shouldDispatchEvents = (flags & DispatchInputAndChangeEvent) &&
1014 m_lastOnChangeOption != element; 1018 m_lastOnChangeOption != element;
1015 m_lastOnChangeOption = element; 1019 m_lastOnChangeOption = element;
1016 } 1020 }
1017 1021
1018 // For the menu list case, this is what makes the selected element appear. 1022 // For the menu list case, this is what makes the selected element appear.
1019 if (LayoutObject* layoutObject = this->layoutObject()) 1023 if (LayoutObject* layoutObject = this->layoutObject())
1020 layoutObject->updateFromElement(); 1024 layoutObject->updateFromElement();
1021 // PopupMenu::updateFromElement() posts an O(N) task. 1025 // PopupMenu::updateFromElement() posts an O(N) task.
1022 if (popupIsVisible()) 1026 if (popupIsVisible() && shouldUpdatePopup)
1023 m_popup->updateFromElement(PopupMenu::BySelectionChange); 1027 m_popup->updateFromElement(PopupMenu::BySelectionChange);
1024 1028
1025 scrollToSelection(); 1029 scrollToSelection();
1026 setNeedsValidityCheck(); 1030 setNeedsValidityCheck();
1027 1031
1028 if (usesMenuList()) { 1032 if (usesMenuList()) {
1029 if (shouldDispatchEvents) { 1033 if (shouldDispatchEvents) {
1030 dispatchInputEvent(); 1034 dispatchInputEvent();
1031 dispatchChangeEvent(); 1035 dispatchChangeEvent();
1032 } 1036 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1065 // made. This matches other browsers' behavior. 1069 // made. This matches other browsers' behavior.
1066 if (usesMenuList()) 1070 if (usesMenuList())
1067 dispatchInputAndChangeEventForMenuList(); 1071 dispatchInputAndChangeEventForMenuList();
1068 m_lastOnChangeSelection.clear(); 1072 m_lastOnChangeSelection.clear();
1069 if (popupIsVisible()) 1073 if (popupIsVisible())
1070 hidePopup(); 1074 hidePopup();
1071 HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement, type, 1075 HTMLFormControlElementWithState::dispatchBlurEvent(newFocusedElement, type,
1072 sourceCapabilities); 1076 sourceCapabilities);
1073 } 1077 }
1074 1078
1075 void HTMLSelectElement::deselectItemsWithoutValidation( 1079 // Returns true if selection state of any OPTIONs is changed.
1080 bool HTMLSelectElement::deselectItemsWithoutValidation(
1076 HTMLOptionElement* excludeElement) { 1081 HTMLOptionElement* excludeElement) {
1077 if (!isMultiple() && usesMenuList() && m_lastOnChangeOption && 1082 if (!isMultiple() && usesMenuList() && m_lastOnChangeOption &&
1078 m_lastOnChangeOption != excludeElement) { 1083 m_lastOnChangeOption != excludeElement) {
1079 m_lastOnChangeOption->setSelectedState(false); 1084 m_lastOnChangeOption->setSelectedState(false);
1080 return; 1085 return true;
1081 } 1086 }
1087 bool didUpdateSelection = false;
1082 for (const auto& option : optionList()) { 1088 for (const auto& option : optionList()) {
1083 if (option != excludeElement) 1089 if (option != excludeElement) {
1090 if (option->selected())
1091 didUpdateSelection = true;
1084 option->setSelectedState(false); 1092 option->setSelectedState(false);
1093 }
1085 } 1094 }
1095 return didUpdateSelection;
1086 } 1096 }
1087 1097
1088 FormControlState HTMLSelectElement::saveFormControlState() const { 1098 FormControlState HTMLSelectElement::saveFormControlState() const {
1089 const ListItems& items = listItems(); 1099 const ListItems& items = listItems();
1090 size_t length = items.size(); 1100 size_t length = items.size();
1091 FormControlState state; 1101 FormControlState state;
1092 for (unsigned i = 0; i < length; ++i) { 1102 for (unsigned i = 0; i < length; ++i) {
1093 if (!isHTMLOptionElement(*items[i])) 1103 if (!isHTMLOptionElement(*items[i]))
1094 continue; 1104 continue;
1095 HTMLOptionElement* option = toHTMLOptionElement(items[i]); 1105 HTMLOptionElement* option = toHTMLOptionElement(items[i]);
(...skipping 925 matching lines...) Expand 10 before | Expand all | Expand 10 after
2021 m_popupUpdater = nullptr; 2031 m_popupUpdater = nullptr;
2022 } 2032 }
2023 2033
2024 void HTMLSelectElement::didMutateSubtree() { 2034 void HTMLSelectElement::didMutateSubtree() {
2025 DCHECK(popupIsVisible()); 2035 DCHECK(popupIsVisible());
2026 DCHECK(m_popup); 2036 DCHECK(m_popup);
2027 m_popup->updateFromElement(PopupMenu::ByDOMChange); 2037 m_popup->updateFromElement(PopupMenu::ByDOMChange);
2028 } 2038 }
2029 2039
2030 } // namespace blink 2040 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/html/HTMLSelectElement.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698