Chromium Code Reviews| 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 reserved. | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved. |
| 7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) | 7 * (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
| 8 * Copyright (C) 2010 Google Inc. All rights reserved. | 8 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) | 9 * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmo bile.com/) |
| 10 * | 10 * |
| (...skipping 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 870 firstEnabledOption = option; | 870 firstEnabledOption = option; |
| 871 firstEnabledOptionIndex = optionIndex; | 871 firstEnabledOptionIndex = optionIndex; |
| 872 if (reason == ResetReasonSelectedOptionRemoved) { | 872 if (reason == ResetReasonSelectedOptionRemoved) { |
| 873 // There must be no selected OPTIONs. | 873 // There must be no selected OPTIONs. |
| 874 break; | 874 break; |
| 875 } | 875 } |
| 876 } | 876 } |
| 877 ++optionIndex; | 877 ++optionIndex; |
| 878 } | 878 } |
| 879 if (!lastSelectedOption && m_size <= 1 && firstEnabledOption && !firstEnable dOption->selected()) { | 879 if (!lastSelectedOption && m_size <= 1 && firstEnabledOption && !firstEnable dOption->selected()) { |
| 880 selectOption(firstEnabledOption, firstEnabledOptionIndex, 0); | 880 selectOption(firstEnabledOption, firstEnabledOptionIndex, reason == Rese tReasonSelectedOptionRemoved ? 0 : DeselectOtherOptions); |
|
tkent
2016/06/29 04:45:56
This is the main change.
| |
| 881 lastSelectedOption = firstEnabledOption; | 881 lastSelectedOption = firstEnabledOption; |
| 882 didChange = true; | 882 didChange = true; |
| 883 } | 883 } |
| 884 if (didChange) | 884 if (didChange) |
| 885 setNeedsValidityCheck(); | 885 setNeedsValidityCheck(); |
| 886 m_lastOnChangeOption = lastSelectedOption; | 886 m_lastOnChangeOption = lastSelectedOption; |
| 887 } | 887 } |
| 888 | 888 |
| 889 HTMLOptionElement* HTMLSelectElement::selectedOption() const | 889 HTMLOptionElement* HTMLSelectElement::selectedOption() const |
| 890 { | 890 { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 960 if (!layoutObject() || !layoutObject()->isListBox()) | 960 if (!layoutObject() || !layoutObject()->isListBox()) |
| 961 return; | 961 return; |
| 962 LayoutRect bounds = option->boundingBox(); | 962 LayoutRect bounds = option->boundingBox(); |
| 963 toLayoutListBox(layoutObject())->scrollToRect(bounds); | 963 toLayoutListBox(layoutObject())->scrollToRect(bounds); |
| 964 } | 964 } |
| 965 | 965 |
| 966 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected) | 966 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b ool optionIsSelected) |
| 967 { | 967 { |
| 968 ASSERT(option->ownerSelectElement() == this); | 968 ASSERT(option->ownerSelectElement() == this); |
| 969 if (optionIsSelected) | 969 if (optionIsSelected) |
| 970 selectOption(option); | 970 selectOption(option, multiple() ? 0 : DeselectOtherOptions); |
| 971 else if (!usesMenuList() || multiple()) | 971 else if (!usesMenuList() || multiple()) |
| 972 selectOption(nullptr); | 972 selectOption(nullptr, multiple() ? 0 : DeselectOtherOptions); |
| 973 else | 973 else |
| 974 selectOption(nextSelectableOption(nullptr)); | 974 selectOption(nextSelectableOption(nullptr), DeselectOtherOptions); |
| 975 } | 975 } |
| 976 | 976 |
| 977 void HTMLSelectElement::optionInserted(HTMLOptionElement& option, bool optionIsS elected) | 977 void HTMLSelectElement::optionInserted(HTMLOptionElement& option, bool optionIsS elected) |
| 978 { | 978 { |
| 979 ASSERT(option.ownerSelectElement() == this); | 979 ASSERT(option.ownerSelectElement() == this); |
| 980 setRecalcListItems(); | 980 setRecalcListItems(); |
| 981 if (optionIsSelected) { | 981 if (optionIsSelected) { |
| 982 selectOption(&option); | 982 selectOption(&option, multiple() ? 0 : DeselectOtherOptions); |
| 983 } else { | 983 } else { |
| 984 // No need to reset if we already have a selected option. | 984 // No need to reset if we already have a selected option. |
| 985 if (!m_lastOnChangeOption) | 985 if (!m_lastOnChangeOption) |
| 986 resetToDefaultSelection(); | 986 resetToDefaultSelection(); |
| 987 } | 987 } |
| 988 } | 988 } |
| 989 | 989 |
| 990 void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option) | 990 void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option) |
| 991 { | 991 { |
| 992 setRecalcListItems(); | 992 setRecalcListItems(); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1014 void HTMLSelectElement::selectOption(HTMLOptionElement* option, SelectOptionFlag s flags) | 1014 void HTMLSelectElement::selectOption(HTMLOptionElement* option, SelectOptionFlag s flags) |
| 1015 { | 1015 { |
| 1016 selectOption(option, option ? option->index() : -1, flags); | 1016 selectOption(option, option ? option->index() : -1, flags); |
| 1017 } | 1017 } |
| 1018 | 1018 |
| 1019 // TODO(tkent): This function is not efficient. It contains multiple O(N) | 1019 // TODO(tkent): This function is not efficient. It contains multiple O(N) |
| 1020 // operations. crbug.com/577989. | 1020 // operations. crbug.com/577989. |
| 1021 void HTMLSelectElement::selectOption(HTMLOptionElement* element, int optionIndex , SelectOptionFlags flags) | 1021 void HTMLSelectElement::selectOption(HTMLOptionElement* element, int optionIndex , SelectOptionFlags flags) |
| 1022 { | 1022 { |
| 1023 TRACE_EVENT0("blink", "HTMLSelectElement::selectOption"); | 1023 TRACE_EVENT0("blink", "HTMLSelectElement::selectOption"); |
| 1024 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); | |
| 1025 | |
| 1026 ASSERT((!element && optionIndex < 0) || (element && optionIndex >= 0)); | 1024 ASSERT((!element && optionIndex < 0) || (element && optionIndex >= 0)); |
| 1027 | 1025 |
| 1028 // selectedIndex() is O(N). | 1026 // selectedIndex() is O(N). |
| 1029 if (isAutofilled() && selectedIndex() != optionIndex) | 1027 if (isAutofilled() && selectedIndex() != optionIndex) |
| 1030 setAutofilled(false); | 1028 setAutofilled(false); |
| 1031 | 1029 |
| 1032 if (element) { | 1030 if (element) { |
| 1033 element->setSelectedState(true); | 1031 element->setSelectedState(true); |
| 1034 if (flags & MakeOptionDirty) | 1032 if (flags & MakeOptionDirty) |
| 1035 element->setDirty(true); | 1033 element->setDirty(true); |
| 1036 } | 1034 } |
| 1037 | 1035 |
| 1038 // deselectItemsWithoutValidation() is O(N). | 1036 // deselectItemsWithoutValidation() is O(N). |
| 1039 if (shouldDeselect) | 1037 if (flags & DeselectOtherOptions) |
| 1040 deselectItemsWithoutValidation(element); | 1038 deselectItemsWithoutValidation(element); |
| 1041 | 1039 |
| 1042 // We should update active selection after finishing OPTION state change | 1040 // We should update active selection after finishing OPTION state change |
| 1043 // because setActiveSelectionAnchorIndex() stores OPTION's selection state. | 1041 // because setActiveSelectionAnchorIndex() stores OPTION's selection state. |
| 1044 if (element) { | 1042 if (element) { |
| 1045 // setActiveSelectionAnchor is O(N). | 1043 // setActiveSelectionAnchor is O(N). |
| 1046 if (!m_activeSelectionAnchor || shouldDeselect) | 1044 if (!m_activeSelectionAnchor || !multiple() || flags & DeselectOtherOpti ons) |
| 1047 setActiveSelectionAnchor(element); | 1045 setActiveSelectionAnchor(element); |
| 1048 if (!m_activeSelectionEnd || shouldDeselect) | 1046 if (!m_activeSelectionEnd || !multiple() || flags & DeselectOtherOptions ) |
| 1049 setActiveSelectionEnd(element); | 1047 setActiveSelectionEnd(element); |
| 1050 } | 1048 } |
| 1051 | 1049 |
| 1052 // For the menu list case, this is what makes the selected element appear. | 1050 // For the menu list case, this is what makes the selected element appear. |
| 1053 if (LayoutObject* layoutObject = this->layoutObject()) | 1051 if (LayoutObject* layoutObject = this->layoutObject()) |
| 1054 layoutObject->updateFromElement(); | 1052 layoutObject->updateFromElement(); |
| 1055 // PopupMenu::updateFromElement() posts an O(N) task. | 1053 // PopupMenu::updateFromElement() posts an O(N) task. |
| 1056 if (popupIsVisible()) | 1054 if (popupIsVisible()) |
| 1057 m_popup->updateFromElement(PopupMenu::BySelectionChange); | 1055 m_popup->updateFromElement(PopupMenu::BySelectionChange); |
| 1058 | 1056 |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1757 const ListItems& items = listItems(); | 1755 const ListItems& items = listItems(); |
| 1758 int listIndex = optionToListIndex(index); | 1756 int listIndex = optionToListIndex(index); |
| 1759 if (listIndex < 0) | 1757 if (listIndex < 0) |
| 1760 return; | 1758 return; |
| 1761 HTMLElement& element = *items[listIndex]; | 1759 HTMLElement& element = *items[listIndex]; |
| 1762 if (!isHTMLOptionElement(element)) | 1760 if (!isHTMLOptionElement(element)) |
| 1763 return; | 1761 return; |
| 1764 EventQueueScope scope; | 1762 EventQueueScope scope; |
| 1765 // If this index is already selected, unselect. otherwise update the | 1763 // If this index is already selected, unselect. otherwise update the |
| 1766 // selected index. | 1764 // selected index. |
| 1765 SelectOptionFlags flags = DispatchInputAndChangeEvent | (multiple() ? 0 : De selectOtherOptions); | |
| 1767 if (toHTMLOptionElement(element).selected()) { | 1766 if (toHTMLOptionElement(element).selected()) { |
| 1768 if (usesMenuList()) | 1767 if (usesMenuList()) |
| 1769 selectOption(-1, DispatchInputAndChangeEvent); | 1768 selectOption(-1, flags); |
| 1770 else | 1769 else |
| 1771 toHTMLOptionElement(element).setSelectedState(false); | 1770 toHTMLOptionElement(element).setSelectedState(false); |
| 1772 } else { | 1771 } else { |
| 1773 selectOption(index, DispatchInputAndChangeEvent); | 1772 selectOption(index, flags); |
| 1774 } | 1773 } |
| 1775 toHTMLOptionElement(element).setDirty(true); | 1774 toHTMLOptionElement(element).setDirty(true); |
| 1776 if (usesMenuList()) | 1775 if (usesMenuList()) |
| 1777 return; | 1776 return; |
| 1778 listBoxOnChange(); | 1777 listBoxOnChange(); |
| 1779 scrollToSelection(); | 1778 scrollToSelection(); |
| 1780 } | 1779 } |
| 1781 | 1780 |
| 1782 unsigned HTMLSelectElement::length() const | 1781 unsigned HTMLSelectElement::length() const |
| 1783 { | 1782 { |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2078 } | 2077 } |
| 2079 | 2078 |
| 2080 void HTMLSelectElement::didMutateSubtree() | 2079 void HTMLSelectElement::didMutateSubtree() |
| 2081 { | 2080 { |
| 2082 DCHECK(popupIsVisible()); | 2081 DCHECK(popupIsVisible()); |
| 2083 DCHECK(m_popup); | 2082 DCHECK(m_popup); |
| 2084 m_popup->updateFromElement(PopupMenu::ByDOMChange); | 2083 m_popup->updateFromElement(PopupMenu::ByDOMChange); |
| 2085 } | 2084 } |
| 2086 | 2085 |
| 2087 } // namespace blink | 2086 } // namespace blink |
| OLD | NEW |