HTMLSummaryElement.cpp (3813B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/HTMLSummaryElement.h" 8 9 #include "mozilla/EventDispatcher.h" 10 #include "mozilla/MouseEvents.h" 11 #include "mozilla/Preferences.h" 12 #include "mozilla/TextEvents.h" 13 #include "mozilla/dom/HTMLDetailsElement.h" 14 #include "mozilla/dom/HTMLElementBinding.h" 15 #include "mozilla/dom/HTMLUnknownElement.h" 16 #include "nsFocusManager.h" 17 18 NS_IMPL_NS_NEW_HTML_ELEMENT(Summary) 19 20 namespace mozilla::dom { 21 22 HTMLSummaryElement::~HTMLSummaryElement() = default; 23 24 NS_IMPL_ELEMENT_CLONE(HTMLSummaryElement) 25 26 nsresult HTMLSummaryElement::PostHandleEvent(EventChainPostVisitor& aVisitor) { 27 nsresult rv = NS_OK; 28 if (!aVisitor.mPresContext) { 29 return rv; 30 } 31 32 if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault) { 33 return rv; 34 } 35 36 if (!IsMainSummary()) { 37 return rv; 38 } 39 40 WidgetEvent* const event = aVisitor.mEvent; 41 nsCOMPtr<Element> target = 42 do_QueryInterface(event->GetOriginalDOMEventTarget()); 43 if (nsContentUtils::IsInInteractiveHTMLContent(target, this)) { 44 return NS_OK; 45 } 46 47 if (event->HasMouseEventMessage()) { 48 WidgetMouseEvent* mouseEvent = event->AsMouseEvent(); 49 50 if (mouseEvent->IsLeftClickEvent()) { 51 RefPtr<HTMLDetailsElement> details = GetDetails(); 52 MOZ_ASSERT(details, 53 "Expected to find details since this is the main summary!"); 54 55 // When dispatching a synthesized mouse click event to a details element 56 // with 'display: none', both Chrome and Safari do not toggle the 'open' 57 // attribute. We had tried to be compatible with this behavior, but found 58 // more inconsistency in test cases in bug 1245424. So we stop doing that. 59 details->ToggleOpen(); 60 aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; 61 return NS_OK; 62 } 63 } // event->HasMouseEventMessage() 64 65 if (event->HasKeyEventMessage() && event->IsTrusted()) { 66 HandleKeyboardActivation(aVisitor); 67 } 68 return rv; 69 } 70 71 bool HTMLSummaryElement::IsHTMLFocusable(IsFocusableFlags aFlags, 72 bool* aIsFocusable, 73 int32_t* aTabIndex) { 74 bool disallowOverridingFocusability = 75 nsGenericHTMLElement::IsHTMLFocusable(aFlags, aIsFocusable, aTabIndex); 76 77 if (disallowOverridingFocusability || !IsMainSummary()) { 78 return disallowOverridingFocusability; 79 } 80 81 // The main summary element is focusable. 82 *aIsFocusable = true; 83 84 // Give a chance to allow the subclass to override aIsFocusable. 85 return false; 86 } 87 88 int32_t HTMLSummaryElement::TabIndexDefault() { 89 // Make the main summary be able to navigate via tab, and be focusable. 90 // See nsGenericHTMLElement::IsHTMLFocusable(). 91 return IsMainSummary() ? 0 : nsGenericHTMLElement::TabIndexDefault(); 92 } 93 94 bool HTMLSummaryElement::IsMainSummary() const { 95 HTMLDetailsElement* details = GetDetails(); 96 if (!details) { 97 return false; 98 } 99 100 return details->GetFirstSummary() == this || 101 GetContainingShadow() == details->GetShadowRoot(); 102 } 103 104 HTMLDetailsElement* HTMLSummaryElement::GetDetails() const { 105 if (auto* details = HTMLDetailsElement::FromNodeOrNull(GetParent())) { 106 return details; 107 } 108 if (!HasBeenInUAWidget()) { 109 return nullptr; 110 } 111 return HTMLDetailsElement::FromNodeOrNull(GetContainingShadowHost()); 112 } 113 114 JSObject* HTMLSummaryElement::WrapNode(JSContext* aCx, 115 JS::Handle<JSObject*> aGivenProto) { 116 return HTMLElement_Binding::Wrap(aCx, this, aGivenProto); 117 } 118 119 } // namespace mozilla::dom