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