mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1823359 - Implement beforetoggle event for popover. r=emilio,smaug
Differential Revision: https://phabricator.services.mozilla.com/D172993
This commit is contained in:
parent
ccd92f0540
commit
dcf61da9a0
@ -223,6 +223,7 @@
|
||||
#include "mozilla/dom/StyleSheetApplicableStateChangeEventBinding.h"
|
||||
#include "mozilla/dom/StyleSheetList.h"
|
||||
#include "mozilla/dom/TimeoutManager.h"
|
||||
#include "mozilla/dom/ToggleEvent.h"
|
||||
#include "mozilla/dom/Touch.h"
|
||||
#include "mozilla/dom/TouchEvent.h"
|
||||
#include "mozilla/dom/TreeOrderedArrayInlines.h"
|
||||
@ -14895,18 +14896,30 @@ void Document::HideAllPopoversUntil(nsINode& aEndpoint,
|
||||
}
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-hidepopover
|
||||
void Document::HidePopover(Element& aPopover, bool aFocusPreviousElement,
|
||||
bool aFireEvents, ErrorResult& aRv) {
|
||||
auto* popoverHTMLEl = nsGenericHTMLElement::FromNode(aPopover);
|
||||
RefPtr<nsGenericHTMLElement> popoverHTMLEl =
|
||||
nsGenericHTMLElement::FromNode(aPopover);
|
||||
NS_ASSERTION(popoverHTMLEl, "Not a HTML element");
|
||||
|
||||
if (!popoverHTMLEl->CheckPopoverValidity(PopoverVisibilityState::Hidden,
|
||||
if (!popoverHTMLEl->CheckPopoverValidity(PopoverVisibilityState::Showing,
|
||||
aRv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Run auto popover steps.
|
||||
// TODO: Fire beforetoggle event and re-check popover validity.
|
||||
// Fire beforetoggle event and re-check popover validity.
|
||||
if (aFireEvents) {
|
||||
// Intentionally ignore the return value here as only on open event the
|
||||
// cancelable attribute is initialized to true.
|
||||
popoverHTMLEl->FireBeforeToggle(true);
|
||||
if (!popoverHTMLEl->CheckPopoverValidity(PopoverVisibilityState::Showing,
|
||||
aRv)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove from Top Layer.
|
||||
|
||||
popoverHTMLEl->PopoverPseudoStateUpdate(false, true);
|
||||
@ -14914,6 +14927,7 @@ void Document::HidePopover(Element& aPopover, bool aFocusPreviousElement,
|
||||
PopoverVisibilityState::Hidden);
|
||||
|
||||
// TODO: Queue popover toggle event task.
|
||||
// TODO: Handle element focus.
|
||||
}
|
||||
|
||||
nsTArray<Element*> Document::AutoPopoverList() const {
|
||||
|
@ -149,6 +149,7 @@
|
||||
#endif /* BEFOREUNLOAD_EVENT */
|
||||
|
||||
EVENT(abort, eImageAbort, EventNameType_All, eBasicEventClass)
|
||||
EVENT(beforetoggle, eBeforeToggle, EventNameType_HTMLXUL, eBasicEventClass)
|
||||
EVENT(bounce, eMarqueeBounce, EventNameType_HTMLMarqueeOnly, eBasicEventClass)
|
||||
EVENT(canplay, eCanPlay, EventNameType_HTML, eBasicEventClass)
|
||||
EVENT(canplaythrough, eCanPlayThrough, EventNameType_HTML, eBasicEventClass)
|
||||
|
@ -92,6 +92,7 @@
|
||||
#include "nsTextFragment.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/MouseEventBinding.h"
|
||||
#include "mozilla/dom/ToggleEvent.h"
|
||||
#include "mozilla/dom/TouchEvent.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "nsHTMLDocument.h"
|
||||
@ -673,14 +674,17 @@ nsresult nsGenericHTMLElement::AfterSetAttr(
|
||||
// The missing value default is the no popover state.
|
||||
newState = PopoverState::None;
|
||||
}
|
||||
if (newState != GetPopoverState()) {
|
||||
if (PopoverOpen()) {
|
||||
HidePopover(IgnoreErrors());
|
||||
PopoverState oldState = GetPopoverState();
|
||||
if (newState != oldState) {
|
||||
if (oldState != PopoverState::None) {
|
||||
HidePopoverInternal(/* aFireEvents = */ false, IgnoreErrors());
|
||||
}
|
||||
if (newState == PopoverState::None) {
|
||||
ClearPopoverData();
|
||||
} else {
|
||||
if (newState != PopoverState::None) {
|
||||
EnsurePopoverData().SetPopoverState(newState);
|
||||
PopoverPseudoStateUpdate(false, true);
|
||||
} else {
|
||||
ClearPopoverData();
|
||||
RemoveStates(ElementState::OPEN | ElementState::CLOSED);
|
||||
}
|
||||
}
|
||||
} else if (aName == nsGkAtoms::dir) {
|
||||
@ -3182,24 +3186,57 @@ void nsGenericHTMLElement::PopoverPseudoStateUpdate(bool aOpen, bool aNotify) {
|
||||
ToggleStates(changedStates, aNotify);
|
||||
}
|
||||
|
||||
bool nsGenericHTMLElement::FireBeforeToggle(bool aIsOpen) {
|
||||
ToggleEventInit init;
|
||||
init.mBubbles = false;
|
||||
if (aIsOpen) {
|
||||
init.mCancelable = false;
|
||||
init.mOldState = u"open"_ns;
|
||||
init.mNewState = u"closed"_ns;
|
||||
} else {
|
||||
init.mCancelable = true;
|
||||
init.mOldState = u"closed"_ns;
|
||||
init.mNewState = u"open"_ns;
|
||||
}
|
||||
RefPtr<ToggleEvent> event =
|
||||
ToggleEvent::Constructor(this, u"beforetoggle"_ns, init);
|
||||
event->SetTrusted(true);
|
||||
|
||||
EventDispatcher::DispatchDOMEvent(MOZ_KnownLive(ToSupports(this)), nullptr,
|
||||
event, nullptr, nullptr);
|
||||
return event->DefaultPrevented();
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-showpopover
|
||||
void nsGenericHTMLElement::ShowPopover(ErrorResult& aRv) {
|
||||
if (!CheckPopoverValidity(PopoverVisibilityState::Hidden, aRv)) {
|
||||
return;
|
||||
}
|
||||
// TODO: Fire beforetoggle event and re-check popover validity.
|
||||
// Fire beforetoggle event and re-check popover validity.
|
||||
if (FireBeforeToggle(false)) {
|
||||
return;
|
||||
}
|
||||
if (!CheckPopoverValidity(PopoverVisibilityState::Hidden, aRv)) {
|
||||
return;
|
||||
}
|
||||
// TODO: Run auto popover steps.
|
||||
// TODO: Add to Top Layer.
|
||||
GetPopoverData()->SetPopoverVisibilityState(PopoverVisibilityState::Showing);
|
||||
|
||||
PopoverPseudoStateUpdate(true, true);
|
||||
GetPopoverData()->SetPopoverVisibilityState(PopoverVisibilityState::Showing);
|
||||
|
||||
// TODO: Handle popover focusing.
|
||||
// TODO: Queue popover toggle event task.
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#dom-hidepopover
|
||||
void nsGenericHTMLElement::HidePopover(ErrorResult& aRv) {
|
||||
OwnerDoc()->HidePopover(*this, true, true, aRv);
|
||||
HidePopoverInternal(true, aRv);
|
||||
}
|
||||
|
||||
void nsGenericHTMLElement::HidePopoverInternal(bool aFireEvents,
|
||||
ErrorResult& aRv) {
|
||||
OwnerDoc()->HidePopover(*this, true, aFireEvents, aRv);
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/popover.html#dom-togglepopover
|
||||
|
@ -155,7 +155,11 @@ class nsGenericHTMLElement : public nsGenericHTMLElementBase {
|
||||
bool PopoverOpen() const;
|
||||
bool CheckPopoverValidity(mozilla::dom::PopoverVisibilityState aExpectedState,
|
||||
ErrorResult& aRv);
|
||||
void ShowPopover(ErrorResult& aRv);
|
||||
/** Returns true if the event has been cancelled. */
|
||||
MOZ_CAN_RUN_SCRIPT bool FireBeforeToggle(bool aIsOpen);
|
||||
MOZ_CAN_RUN_SCRIPT void ShowPopover(ErrorResult& aRv);
|
||||
MOZ_CAN_RUN_SCRIPT void HidePopoverInternal(bool aFireEvents,
|
||||
ErrorResult& aRv);
|
||||
MOZ_CAN_RUN_SCRIPT void HidePopover(ErrorResult& aRv);
|
||||
MOZ_CAN_RUN_SCRIPT void TogglePopover(bool force, ErrorResult& aRv);
|
||||
|
||||
|
@ -33,6 +33,8 @@ interface mixin GlobalEventHandlers {
|
||||
attribute EventHandler onauxclick;
|
||||
[Pref="dom.input_events.beforeinput.enabled"]
|
||||
attribute EventHandler onbeforeinput;
|
||||
[Pref="dom.element.popover.enabled"]
|
||||
attribute EventHandler onbeforetoggle;
|
||||
attribute EventHandler oncanplay;
|
||||
attribute EventHandler oncanplaythrough;
|
||||
attribute EventHandler onchange;
|
||||
|
@ -63,9 +63,6 @@
|
||||
[Removing a visible popover=auto element from the document should close the popover]
|
||||
expected: FAIL
|
||||
|
||||
[A showing popover=auto does not match :modal]
|
||||
expected: FAIL
|
||||
|
||||
[Removing a visible popover=hint element from the document should close the popover]
|
||||
expected: FAIL
|
||||
|
||||
@ -75,9 +72,6 @@
|
||||
[Removing a visible popover=manual element from the document should close the popover]
|
||||
expected: FAIL
|
||||
|
||||
[A showing popover=manual does not match :modal]
|
||||
expected: FAIL
|
||||
|
||||
[Changing the popover type in a "beforetoggle" event handler should throw an exception (during showPopover())]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
[popover-beforetoggle-opening-event.html]
|
||||
[Ensure the `beforetoggle` event can be used to populate content before the popover renders]
|
||||
expected: FAIL
|
@ -4,3 +4,6 @@
|
||||
|
||||
[Popover focus returns when popover is hidden by invoker]
|
||||
expected: FAIL
|
||||
|
||||
[Circular reference tab navigation]
|
||||
expected: FAIL
|
||||
|
@ -1,7 +1,4 @@
|
||||
[popover-focus-child-dialog.html]
|
||||
max-asserts: 2
|
||||
expected:
|
||||
if (os == "android") and fission: [ERROR, TIMEOUT]
|
||||
ERROR
|
||||
max-asserts: 2
|
||||
[Popovers should not initially focus child popover elements.]
|
||||
expected: NOTRUN
|
||||
|
@ -24,9 +24,6 @@
|
||||
[Clicking inside a parent popover should close child popover]
|
||||
expected: FAIL
|
||||
|
||||
[Clicking on invoking element, after using it for activation, shouldn't close its popover]
|
||||
expected: FAIL
|
||||
|
||||
[Clicking on invoking element, after using it for activation, shouldn't close its popover (nested case)]
|
||||
expected: FAIL
|
||||
|
||||
@ -58,10 +55,7 @@
|
||||
expected: FAIL
|
||||
|
||||
[Scrolling within a popover should not close the popover]
|
||||
expected: FAIL
|
||||
|
||||
[Moving focus back to the anchor element should not dismiss the popover]
|
||||
expected: FAIL
|
||||
expected: [FAIL, PASS]
|
||||
|
||||
[Ensure circular/convoluted ancestral relationships are functional]
|
||||
expected: FAIL
|
||||
|
@ -1,3 +0,0 @@
|
||||
[popover-not-keyboard-focusable.html]
|
||||
[Popover should not be keyboard focusable]
|
||||
expected: FAIL
|
@ -1,7 +1,4 @@
|
||||
[popover-shadow-dom.html]
|
||||
[Popovers located inside shadow DOM can still be shown]
|
||||
expected: FAIL
|
||||
|
||||
[anchor references do not cross shadow boundaries]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -1,28 +1,12 @@
|
||||
[popover-top-layer-interactions.html]
|
||||
expected: ERROR
|
||||
[A Popover API should close a Popover API]
|
||||
expected: FAIL
|
||||
|
||||
[A Modal Dialog should close a Popover API]
|
||||
expected: NOTRUN
|
||||
expected: FAIL
|
||||
|
||||
[A Fullscreen Element should close a Popover API]
|
||||
expected: NOTRUN
|
||||
|
||||
[A Popover API should *not* close a Modal Dialog]
|
||||
expected: NOTRUN
|
||||
|
||||
[A Popover API should *not* close a Fullscreen Element]
|
||||
expected: NOTRUN
|
||||
expected: FAIL
|
||||
|
||||
[A Fullscreen Element should *not* close a Fullscreen Element]
|
||||
expected: NOTRUN
|
||||
|
||||
[A Modal Dialog should *not* close a Modal Dialog]
|
||||
expected: NOTRUN
|
||||
|
||||
[A Fullscreen Element should *not* close a Modal Dialog]
|
||||
expected: NOTRUN
|
||||
|
||||
[A Modal Dialog should *not* close a Fullscreen Element]
|
||||
expected: NOTRUN
|
||||
expected: FAIL
|
||||
|
@ -90,6 +90,8 @@ NS_EVENT_MESSAGE(eContextMenu)
|
||||
|
||||
NS_EVENT_MESSAGE(eCueChange)
|
||||
|
||||
NS_EVENT_MESSAGE(eBeforeToggle)
|
||||
|
||||
NS_EVENT_MESSAGE(eLoad)
|
||||
NS_EVENT_MESSAGE(eUnload)
|
||||
NS_EVENT_MESSAGE(eHashChange)
|
||||
|
@ -1980,6 +1980,7 @@ STATIC_ATOMS = [
|
||||
Atom("onmozshowdropdown_sourcetouch", "onmozshowdropdown-sourcetouch"),
|
||||
Atom("onprintPreviewUpdate", "onprintPreviewUpdate"),
|
||||
Atom("onscrollend", "onscrollend"),
|
||||
Atom("onbeforetoggle", "onbeforetoggle"),
|
||||
# WebExtensions
|
||||
Atom("moz_extension", "moz-extension"),
|
||||
Atom("all_urlsPermission", "<all_urls>"),
|
||||
|
Loading…
Reference in New Issue
Block a user