| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |