| 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 869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 firstEnabledOption = option; | 880 firstEnabledOption = option; |
| 881 firstEnabledOptionIndex = optionIndex; | 881 firstEnabledOptionIndex = optionIndex; |
| 882 if (reason == ResetReasonSelectedOptionRemoved) { | 882 if (reason == ResetReasonSelectedOptionRemoved) { |
| 883 // There must be no selected OPTIONs. | 883 // There must be no selected OPTIONs. |
| 884 break; | 884 break; |
| 885 } | 885 } |
| 886 } | 886 } |
| 887 ++optionIndex; | 887 ++optionIndex; |
| 888 } | 888 } |
| 889 if (!lastSelectedOption && m_size <= 1 && firstEnabledOption && !firstEnable
dOption->selected()) { | 889 if (!lastSelectedOption && m_size <= 1 && firstEnabledOption && !firstEnable
dOption->selected()) { |
| 890 selectOption(firstEnabledOption, firstEnabledOptionIndex, 0); | 890 selectOption(firstEnabledOption, firstEnabledOptionIndex, reason == Rese
tReasonSelectedOptionRemoved ? 0 : DeselectOtherOptions); |
| 891 lastSelectedOption = firstEnabledOption; | 891 lastSelectedOption = firstEnabledOption; |
| 892 didChange = true; | 892 didChange = true; |
| 893 } | 893 } |
| 894 if (didChange) | 894 if (didChange) |
| 895 setNeedsValidityCheck(); | 895 setNeedsValidityCheck(); |
| 896 m_lastOnChangeOption = lastSelectedOption; | 896 m_lastOnChangeOption = lastSelectedOption; |
| 897 } | 897 } |
| 898 | 898 |
| 899 HTMLOptionElement* HTMLSelectElement::selectedOption() const | 899 HTMLOptionElement* HTMLSelectElement::selectedOption() const |
| 900 { | 900 { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 970 if (!layoutObject() || !layoutObject()->isListBox()) | 970 if (!layoutObject() || !layoutObject()->isListBox()) |
| 971 return; | 971 return; |
| 972 LayoutRect bounds = option->boundingBox(); | 972 LayoutRect bounds = option->boundingBox(); |
| 973 toLayoutListBox(layoutObject())->scrollToRect(bounds); | 973 toLayoutListBox(layoutObject())->scrollToRect(bounds); |
| 974 } | 974 } |
| 975 | 975 |
| 976 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b
ool optionIsSelected) | 976 void HTMLSelectElement::optionSelectionStateChanged(HTMLOptionElement* option, b
ool optionIsSelected) |
| 977 { | 977 { |
| 978 ASSERT(option->ownerSelectElement() == this); | 978 ASSERT(option->ownerSelectElement() == this); |
| 979 if (optionIsSelected) | 979 if (optionIsSelected) |
| 980 selectOption(option); | 980 selectOption(option, multiple() ? 0 : DeselectOtherOptions); |
| 981 else if (!usesMenuList() || multiple()) | 981 else if (!usesMenuList() || multiple()) |
| 982 selectOption(nullptr); | 982 selectOption(nullptr, multiple() ? 0 : DeselectOtherOptions); |
| 983 else | 983 else |
| 984 selectOption(nextSelectableOption(nullptr)); | 984 selectOption(nextSelectableOption(nullptr), DeselectOtherOptions); |
| 985 } | 985 } |
| 986 | 986 |
| 987 void HTMLSelectElement::optionInserted(HTMLOptionElement& option, bool optionIsS
elected) | 987 void HTMLSelectElement::optionInserted(HTMLOptionElement& option, bool optionIsS
elected) |
| 988 { | 988 { |
| 989 ASSERT(option.ownerSelectElement() == this); | 989 ASSERT(option.ownerSelectElement() == this); |
| 990 setRecalcListItems(); | 990 setRecalcListItems(); |
| 991 if (optionIsSelected) { | 991 if (optionIsSelected) { |
| 992 selectOption(&option); | 992 selectOption(&option, multiple() ? 0 : DeselectOtherOptions); |
| 993 } else { | 993 } else { |
| 994 // No need to reset if we already have a selected option. | 994 // No need to reset if we already have a selected option. |
| 995 if (!m_lastOnChangeOption) | 995 if (!m_lastOnChangeOption) |
| 996 resetToDefaultSelection(); | 996 resetToDefaultSelection(); |
| 997 } | 997 } |
| 998 } | 998 } |
| 999 | 999 |
| 1000 void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option) | 1000 void HTMLSelectElement::optionRemoved(const HTMLOptionElement& option) |
| 1001 { | 1001 { |
| 1002 setRecalcListItems(); | 1002 setRecalcListItems(); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1024 void HTMLSelectElement::selectOption(HTMLOptionElement* option, SelectOptionFlag
s flags) | 1024 void HTMLSelectElement::selectOption(HTMLOptionElement* option, SelectOptionFlag
s flags) |
| 1025 { | 1025 { |
| 1026 selectOption(option, option ? option->index() : -1, flags); | 1026 selectOption(option, option ? option->index() : -1, flags); |
| 1027 } | 1027 } |
| 1028 | 1028 |
| 1029 // TODO(tkent): This function is not efficient. It contains multiple O(N) | 1029 // TODO(tkent): This function is not efficient. It contains multiple O(N) |
| 1030 // operations. crbug.com/577989. | 1030 // operations. crbug.com/577989. |
| 1031 void HTMLSelectElement::selectOption(HTMLOptionElement* element, int optionIndex
, SelectOptionFlags flags) | 1031 void HTMLSelectElement::selectOption(HTMLOptionElement* element, int optionIndex
, SelectOptionFlags flags) |
| 1032 { | 1032 { |
| 1033 TRACE_EVENT0("blink", "HTMLSelectElement::selectOption"); | 1033 TRACE_EVENT0("blink", "HTMLSelectElement::selectOption"); |
| 1034 bool shouldDeselect = !m_multiple || (flags & DeselectOtherOptions); | |
| 1035 | |
| 1036 ASSERT((!element && optionIndex < 0) || (element && optionIndex >= 0)); | 1034 ASSERT((!element && optionIndex < 0) || (element && optionIndex >= 0)); |
| 1037 | 1035 |
| 1038 // selectedIndex() is O(N). | 1036 // selectedIndex() is O(N). |
| 1039 if (isAutofilled() && selectedIndex() != optionIndex) | 1037 if (isAutofilled() && selectedIndex() != optionIndex) |
| 1040 setAutofilled(false); | 1038 setAutofilled(false); |
| 1041 | 1039 |
| 1042 if (element) { | 1040 if (element) { |
| 1043 element->setSelectedState(true); | 1041 element->setSelectedState(true); |
| 1044 if (flags & MakeOptionDirty) | 1042 if (flags & MakeOptionDirty) |
| 1045 element->setDirty(true); | 1043 element->setDirty(true); |
| 1046 } | 1044 } |
| 1047 | 1045 |
| 1048 // deselectItemsWithoutValidation() is O(N). | 1046 // deselectItemsWithoutValidation() is O(N). |
| 1049 if (shouldDeselect) | 1047 if (flags & DeselectOtherOptions) |
| 1050 deselectItemsWithoutValidation(element); | 1048 deselectItemsWithoutValidation(element); |
| 1051 | 1049 |
| 1052 // We should update active selection after finishing OPTION state change | 1050 // We should update active selection after finishing OPTION state change |
| 1053 // because setActiveSelectionAnchorIndex() stores OPTION's selection state. | 1051 // because setActiveSelectionAnchorIndex() stores OPTION's selection state. |
| 1054 if (element) { | 1052 if (element) { |
| 1055 // setActiveSelectionAnchor is O(N). | 1053 // setActiveSelectionAnchor is O(N). |
| 1056 if (!m_activeSelectionAnchor || shouldDeselect) | 1054 if (!m_activeSelectionAnchor || !multiple() || flags & DeselectOtherOpti
ons) |
| 1057 setActiveSelectionAnchor(element); | 1055 setActiveSelectionAnchor(element); |
| 1058 if (!m_activeSelectionEnd || shouldDeselect) | 1056 if (!m_activeSelectionEnd || !multiple() || flags & DeselectOtherOptions
) |
| 1059 setActiveSelectionEnd(element); | 1057 setActiveSelectionEnd(element); |
| 1060 } | 1058 } |
| 1061 | 1059 |
| 1062 // For the menu list case, this is what makes the selected element appear. | 1060 // For the menu list case, this is what makes the selected element appear. |
| 1063 if (LayoutObject* layoutObject = this->layoutObject()) | 1061 if (LayoutObject* layoutObject = this->layoutObject()) |
| 1064 layoutObject->updateFromElement(); | 1062 layoutObject->updateFromElement(); |
| 1065 // PopupMenu::updateFromElement() posts an O(N) task. | 1063 // PopupMenu::updateFromElement() posts an O(N) task. |
| 1066 if (popupIsVisible()) | 1064 if (popupIsVisible()) |
| 1067 m_popup->updateFromElement(PopupMenu::BySelectionChange); | 1065 m_popup->updateFromElement(PopupMenu::BySelectionChange); |
| 1068 | 1066 |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1769 const ListItems& items = listItems(); | 1767 const ListItems& items = listItems(); |
| 1770 int listIndex = optionToListIndex(index); | 1768 int listIndex = optionToListIndex(index); |
| 1771 if (listIndex < 0) | 1769 if (listIndex < 0) |
| 1772 return; | 1770 return; |
| 1773 HTMLElement& element = *items[listIndex]; | 1771 HTMLElement& element = *items[listIndex]; |
| 1774 if (!isHTMLOptionElement(element)) | 1772 if (!isHTMLOptionElement(element)) |
| 1775 return; | 1773 return; |
| 1776 EventQueueScope scope; | 1774 EventQueueScope scope; |
| 1777 // If this index is already selected, unselect. otherwise update the | 1775 // If this index is already selected, unselect. otherwise update the |
| 1778 // selected index. | 1776 // selected index. |
| 1777 SelectOptionFlags flags = DispatchInputAndChangeEvent | (multiple() ? 0 : De
selectOtherOptions); |
| 1779 if (toHTMLOptionElement(element).selected()) { | 1778 if (toHTMLOptionElement(element).selected()) { |
| 1780 if (usesMenuList()) | 1779 if (usesMenuList()) |
| 1781 selectOption(-1, DispatchInputAndChangeEvent); | 1780 selectOption(-1, flags); |
| 1782 else | 1781 else |
| 1783 toHTMLOptionElement(element).setSelectedState(false); | 1782 toHTMLOptionElement(element).setSelectedState(false); |
| 1784 } else { | 1783 } else { |
| 1785 selectOption(index, DispatchInputAndChangeEvent); | 1784 selectOption(index, flags); |
| 1786 } | 1785 } |
| 1787 toHTMLOptionElement(element).setDirty(true); | 1786 toHTMLOptionElement(element).setDirty(true); |
| 1788 if (usesMenuList()) | 1787 if (usesMenuList()) |
| 1789 return; | 1788 return; |
| 1790 listBoxOnChange(); | 1789 listBoxOnChange(); |
| 1791 scrollToSelection(); | 1790 scrollToSelection(); |
| 1792 } | 1791 } |
| 1793 | 1792 |
| 1794 unsigned HTMLSelectElement::length() const | 1793 unsigned HTMLSelectElement::length() const |
| 1795 { | 1794 { |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2090 } | 2089 } |
| 2091 | 2090 |
| 2092 void HTMLSelectElement::didMutateSubtree() | 2091 void HTMLSelectElement::didMutateSubtree() |
| 2093 { | 2092 { |
| 2094 DCHECK(popupIsVisible()); | 2093 DCHECK(popupIsVisible()); |
| 2095 DCHECK(m_popup); | 2094 DCHECK(m_popup); |
| 2096 m_popup->updateFromElement(PopupMenu::ByDOMChange); | 2095 m_popup->updateFromElement(PopupMenu::ByDOMChange); |
| 2097 } | 2096 } |
| 2098 | 2097 |
| 2099 } // namespace blink | 2098 } // namespace blink |
| OLD | NEW |