| 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 18 matching lines...) Expand all Loading... |
| 29 | 29 |
| 30 #include "bindings/core/v8/ExceptionMessages.h" | 30 #include "bindings/core/v8/ExceptionMessages.h" |
| 31 #include "bindings/core/v8/ExceptionState.h" | 31 #include "bindings/core/v8/ExceptionState.h" |
| 32 #include "bindings/core/v8/ExceptionStatePlaceholder.h" | 32 #include "bindings/core/v8/ExceptionStatePlaceholder.h" |
| 33 #include "bindings/core/v8/UnionTypesCore.h" | 33 #include "bindings/core/v8/UnionTypesCore.h" |
| 34 #include "core/HTMLNames.h" | 34 #include "core/HTMLNames.h" |
| 35 #include "core/dom/AXObjectCache.h" | 35 #include "core/dom/AXObjectCache.h" |
| 36 #include "core/dom/Attribute.h" | 36 #include "core/dom/Attribute.h" |
| 37 #include "core/dom/ElementTraversal.h" | 37 #include "core/dom/ElementTraversal.h" |
| 38 #include "core/dom/ExecutionContextTask.h" | 38 #include "core/dom/ExecutionContextTask.h" |
| 39 #include "core/dom/MutationCallback.h" |
| 40 #include "core/dom/MutationObserver.h" |
| 41 #include "core/dom/MutationObserverInit.h" |
| 39 #include "core/dom/NodeComputedStyle.h" | 42 #include "core/dom/NodeComputedStyle.h" |
| 40 #include "core/dom/NodeListsNodeData.h" | 43 #include "core/dom/NodeListsNodeData.h" |
| 41 #include "core/dom/NodeTraversal.h" | 44 #include "core/dom/NodeTraversal.h" |
| 42 #include "core/events/GestureEvent.h" | 45 #include "core/events/GestureEvent.h" |
| 43 #include "core/events/KeyboardEvent.h" | 46 #include "core/events/KeyboardEvent.h" |
| 44 #include "core/events/MouseEvent.h" | 47 #include "core/events/MouseEvent.h" |
| 45 #include "core/events/ScopedEventQueue.h" | 48 #include "core/events/ScopedEventQueue.h" |
| 46 #include "core/frame/FrameHost.h" | 49 #include "core/frame/FrameHost.h" |
| 47 #include "core/frame/FrameView.h" | 50 #include "core/frame/FrameView.h" |
| 48 #include "core/frame/LocalFrame.h" | 51 #include "core/frame/LocalFrame.h" |
| (...skipping 869 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 | 921 |
| 919 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) | 922 void HTMLSelectElement::setSuggestedIndex(int suggestedIndex) |
| 920 { | 923 { |
| 921 m_suggestedIndex = suggestedIndex; | 924 m_suggestedIndex = suggestedIndex; |
| 922 | 925 |
| 923 if (LayoutObject* layoutObject = this->layoutObject()) { | 926 if (LayoutObject* layoutObject = this->layoutObject()) { |
| 924 layoutObject->updateFromElement(); | 927 layoutObject->updateFromElement(); |
| 925 scrollToOption(item(listToOptionIndex(suggestedIndex))); | 928 scrollToOption(item(listToOptionIndex(suggestedIndex))); |
| 926 } | 929 } |
| 927 if (popupIsVisible()) | 930 if (popupIsVisible()) |
| 928 m_popup->updateFromElement(); | 931 m_popup->updateFromElement(PopupMenu::BySelectionChange); |
| 929 } | 932 } |
| 930 | 933 |
| 931 void HTMLSelectElement::scrollToOption(HTMLOptionElement* option) | 934 void HTMLSelectElement::scrollToOption(HTMLOptionElement* option) |
| 932 { | 935 { |
| 933 if (!option) | 936 if (!option) |
| 934 return; | 937 return; |
| 935 if (usesMenuList()) | 938 if (usesMenuList()) |
| 936 return; | 939 return; |
| 937 bool hasPendingTask = m_optionToScrollTo; | 940 bool hasPendingTask = m_optionToScrollTo; |
| 938 // We'd like to keep an HTMLOptionElement reference rather than the index of | 941 // We'd like to keep an HTMLOptionElement reference rather than the index of |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1040 setActiveSelectionAnchor(element); | 1043 setActiveSelectionAnchor(element); |
| 1041 if (!m_activeSelectionEnd || shouldDeselect) | 1044 if (!m_activeSelectionEnd || shouldDeselect) |
| 1042 setActiveSelectionEnd(element); | 1045 setActiveSelectionEnd(element); |
| 1043 } | 1046 } |
| 1044 | 1047 |
| 1045 // For the menu list case, this is what makes the selected element appear. | 1048 // For the menu list case, this is what makes the selected element appear. |
| 1046 if (LayoutObject* layoutObject = this->layoutObject()) | 1049 if (LayoutObject* layoutObject = this->layoutObject()) |
| 1047 layoutObject->updateFromElement(); | 1050 layoutObject->updateFromElement(); |
| 1048 // PopupMenu::updateFromElement() posts an O(N) task. | 1051 // PopupMenu::updateFromElement() posts an O(N) task. |
| 1049 if (popupIsVisible()) | 1052 if (popupIsVisible()) |
| 1050 m_popup->updateFromElement(); | 1053 m_popup->updateFromElement(PopupMenu::BySelectionChange); |
| 1051 | 1054 |
| 1052 scrollToSelection(); | 1055 scrollToSelection(); |
| 1053 setNeedsValidityCheck(); | 1056 setNeedsValidityCheck(); |
| 1054 | 1057 |
| 1055 if (usesMenuList()) { | 1058 if (usesMenuList()) { |
| 1056 if (flags & DispatchInputAndChangeEvent) | 1059 if (flags & DispatchInputAndChangeEvent) |
| 1057 dispatchInputAndChangeEventForMenuList(); | 1060 dispatchInputAndChangeEventForMenuList(); |
| 1058 else | 1061 else |
| 1059 m_lastOnChangeOption = element; | 1062 m_lastOnChangeOption = element; |
| 1060 if (LayoutObject* layoutObject = this->layoutObject()) { | 1063 if (LayoutObject* layoutObject = this->layoutObject()) { |
| (...skipping 759 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1820 } | 1823 } |
| 1821 | 1824 |
| 1822 DEFINE_TRACE(HTMLSelectElement) | 1825 DEFINE_TRACE(HTMLSelectElement) |
| 1823 { | 1826 { |
| 1824 visitor->trace(m_listItems); | 1827 visitor->trace(m_listItems); |
| 1825 visitor->trace(m_lastOnChangeOption); | 1828 visitor->trace(m_lastOnChangeOption); |
| 1826 visitor->trace(m_activeSelectionAnchor); | 1829 visitor->trace(m_activeSelectionAnchor); |
| 1827 visitor->trace(m_activeSelectionEnd); | 1830 visitor->trace(m_activeSelectionEnd); |
| 1828 visitor->trace(m_optionToScrollTo); | 1831 visitor->trace(m_optionToScrollTo); |
| 1829 visitor->trace(m_popup); | 1832 visitor->trace(m_popup); |
| 1833 visitor->trace(m_popupUpdater); |
| 1830 HTMLFormControlElementWithState::trace(visitor); | 1834 HTMLFormControlElementWithState::trace(visitor); |
| 1831 } | 1835 } |
| 1832 | 1836 |
| 1833 void HTMLSelectElement::didAddUserAgentShadowRoot(ShadowRoot& root) | 1837 void HTMLSelectElement::didAddUserAgentShadowRoot(ShadowRoot& root) |
| 1834 { | 1838 { |
| 1835 RawPtr<HTMLContentElement> content = HTMLContentElement::create(document()); | 1839 RawPtr<HTMLContentElement> content = HTMLContentElement::create(document()); |
| 1836 content->setAttribute(selectAttr, "option,optgroup,hr"); | 1840 content->setAttribute(selectAttr, "option,optgroup,hr"); |
| 1837 root.appendChild(content); | 1841 root.appendChild(content); |
| 1838 } | 1842 } |
| 1839 | 1843 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1893 LayoutUnit HTMLSelectElement::clientPaddingRight() const | 1897 LayoutUnit HTMLSelectElement::clientPaddingRight() const |
| 1894 { | 1898 { |
| 1895 if (layoutObject() && layoutObject()->isMenuList()) | 1899 if (layoutObject() && layoutObject()->isMenuList()) |
| 1896 return toLayoutMenuList(layoutObject())->clientPaddingRight(); | 1900 return toLayoutMenuList(layoutObject())->clientPaddingRight(); |
| 1897 return LayoutUnit(); | 1901 return LayoutUnit(); |
| 1898 } | 1902 } |
| 1899 | 1903 |
| 1900 void HTMLSelectElement::popupDidHide() | 1904 void HTMLSelectElement::popupDidHide() |
| 1901 { | 1905 { |
| 1902 m_popupIsVisible = false; | 1906 m_popupIsVisible = false; |
| 1907 unobserveTreeMutation(); |
| 1903 if (AXObjectCache* cache = document().existingAXObjectCache()) { | 1908 if (AXObjectCache* cache = document().existingAXObjectCache()) { |
| 1904 if (layoutObject() && layoutObject()->isMenuList()) | 1909 if (layoutObject() && layoutObject()->isMenuList()) |
| 1905 cache->didHideMenuListPopup(toLayoutMenuList(layoutObject())); | 1910 cache->didHideMenuListPopup(toLayoutMenuList(layoutObject())); |
| 1906 } | 1911 } |
| 1907 } | 1912 } |
| 1908 | 1913 |
| 1909 void HTMLSelectElement::setIndexToSelectOnCancel(int listIndex) | 1914 void HTMLSelectElement::setIndexToSelectOnCancel(int listIndex) |
| 1910 { | 1915 { |
| 1911 m_indexToSelectOnCancel = listIndex; | 1916 m_indexToSelectOnCancel = listIndex; |
| 1912 if (layoutObject()) | 1917 if (layoutObject()) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1950 if (popupIsVisible()) | 1955 if (popupIsVisible()) |
| 1951 return; | 1956 return; |
| 1952 if (document().frameHost()->chromeClient().hasOpenedPopup()) | 1957 if (document().frameHost()->chromeClient().hasOpenedPopup()) |
| 1953 return; | 1958 return; |
| 1954 if (!layoutObject() || !layoutObject()->isMenuList()) | 1959 if (!layoutObject() || !layoutObject()->isMenuList()) |
| 1955 return; | 1960 return; |
| 1956 | 1961 |
| 1957 if (!m_popup) | 1962 if (!m_popup) |
| 1958 m_popup = document().frameHost()->chromeClient().openPopupMenu(*document
().frame(), *this); | 1963 m_popup = document().frameHost()->chromeClient().openPopupMenu(*document
().frame(), *this); |
| 1959 m_popupIsVisible = true; | 1964 m_popupIsVisible = true; |
| 1965 observeTreeMutation(); |
| 1960 | 1966 |
| 1961 LayoutMenuList* menuList = toLayoutMenuList(layoutObject()); | 1967 LayoutMenuList* menuList = toLayoutMenuList(layoutObject()); |
| 1962 m_popup->show(); | 1968 m_popup->show(); |
| 1963 if (AXObjectCache* cache = document().existingAXObjectCache()) | 1969 if (AXObjectCache* cache = document().existingAXObjectCache()) |
| 1964 cache->didShowMenuListPopup(menuList); | 1970 cache->didShowMenuListPopup(menuList); |
| 1965 } | 1971 } |
| 1966 | 1972 |
| 1967 void HTMLSelectElement::hidePopup() | 1973 void HTMLSelectElement::hidePopup() |
| 1968 { | 1974 { |
| 1969 if (m_popup) | 1975 if (m_popup) |
| 1970 m_popup->hide(); | 1976 m_popup->hide(); |
| 1971 } | 1977 } |
| 1972 | 1978 |
| 1973 void HTMLSelectElement::didRecalcStyle(StyleRecalcChange change) | 1979 void HTMLSelectElement::didRecalcStyle(StyleRecalcChange change) |
| 1974 { | 1980 { |
| 1975 HTMLFormControlElementWithState::didRecalcStyle(change); | 1981 HTMLFormControlElementWithState::didRecalcStyle(change); |
| 1976 if (popupIsVisible()) | 1982 if (popupIsVisible()) |
| 1977 m_popup->updateFromElement(); | 1983 m_popup->updateFromElement(PopupMenu::ByStyleChange); |
| 1978 } | 1984 } |
| 1979 | 1985 |
| 1980 void HTMLSelectElement::detach(const AttachContext& context) | 1986 void HTMLSelectElement::detach(const AttachContext& context) |
| 1981 { | 1987 { |
| 1982 HTMLFormControlElementWithState::detach(context); | 1988 HTMLFormControlElementWithState::detach(context); |
| 1983 if (m_popup) | 1989 if (m_popup) |
| 1984 m_popup->disconnectClient(); | 1990 m_popup->disconnectClient(); |
| 1985 m_popupIsVisible = false; | 1991 m_popupIsVisible = false; |
| 1986 m_popup = nullptr; | 1992 m_popup = nullptr; |
| 1993 unobserveTreeMutation(); |
| 1987 } | 1994 } |
| 1988 | 1995 |
| 1989 void HTMLSelectElement::resetTypeAheadSessionForTesting() | 1996 void HTMLSelectElement::resetTypeAheadSessionForTesting() |
| 1990 { | 1997 { |
| 1991 m_typeAhead.resetSession(); | 1998 m_typeAhead.resetSession(); |
| 1992 } | 1999 } |
| 1993 | 2000 |
| 2001 // PopupUpdater notifies updates of the specified SELECT element subtree to |
| 2002 // a PopupMenu object. |
| 2003 class HTMLSelectElement::PopupUpdater : public MutationCallback { |
| 2004 public: |
| 2005 explicit PopupUpdater(HTMLSelectElement&); |
| 2006 DECLARE_VIRTUAL_TRACE(); |
| 2007 |
| 2008 void dispose() |
| 2009 { |
| 2010 m_observer->disconnect(); |
| 2011 } |
| 2012 |
| 2013 private: |
| 2014 void call(const HeapVector<Member<MutationRecord>>&, MutationObserver*) over
ride |
| 2015 { |
| 2016 m_select->didMutateSubtree(); |
| 2017 } |
| 2018 |
| 2019 ExecutionContext* getExecutionContext() const override |
| 2020 { |
| 2021 return &m_select->document(); |
| 2022 } |
| 2023 |
| 2024 Member<HTMLSelectElement> m_select; |
| 2025 Member<MutationObserver> m_observer; |
| 2026 }; |
| 2027 |
| 2028 HTMLSelectElement::PopupUpdater::PopupUpdater(HTMLSelectElement& select) |
| 2029 : m_select(select) |
| 2030 { |
| 2031 m_observer = MutationObserver::create(this); |
| 2032 MutationObserverInit init; |
| 2033 init.setAttributes(true); |
| 2034 init.setCharacterData(true); |
| 2035 init.setChildList(true); |
| 2036 init.setSubtree(true); |
| 2037 m_observer->observe(&select, init, ASSERT_NO_EXCEPTION); |
| 2038 } |
| 2039 |
| 2040 DEFINE_TRACE(HTMLSelectElement::PopupUpdater) |
| 2041 { |
| 2042 visitor->trace(m_select); |
| 2043 visitor->trace(m_observer); |
| 2044 MutationCallback::trace(visitor); |
| 2045 } |
| 2046 |
| 2047 void HTMLSelectElement::observeTreeMutation() |
| 2048 { |
| 2049 DCHECK(!m_popupUpdater); |
| 2050 m_popupUpdater = new PopupUpdater(*this); |
| 2051 } |
| 2052 |
| 2053 void HTMLSelectElement::unobserveTreeMutation() |
| 2054 { |
| 2055 if (!m_popupUpdater) |
| 2056 return; |
| 2057 m_popupUpdater->dispose(); |
| 2058 m_popupUpdater = nullptr; |
| 2059 } |
| 2060 |
| 2061 void HTMLSelectElement::didMutateSubtree() |
| 2062 { |
| 2063 DCHECK(popupIsVisible()); |
| 2064 DCHECK(m_popup); |
| 2065 m_popup->updateFromElement(PopupMenu::ByDOMChange); |
| 2066 } |
| 2067 |
| 1994 } // namespace blink | 2068 } // namespace blink |
| OLD | NEW |