зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1800370 - Make form-associate custom element behave the same as other form control element on event dispatching; r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D165292
This commit is contained in:
Родитель
9cf9360385
Коммит
9b1c4ebd8d
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "mozilla/dom/CustomElementRegistry.h"
|
||||
#include "mozilla/dom/HTMLElementBinding.h"
|
||||
#include "mozilla/EventDispatcher.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
@ -38,6 +39,16 @@ JSObject* HTMLElement::WrapNode(JSContext* aCx,
|
|||
return dom::HTMLElement_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void HTMLElement::GetEventTargetParent(EventChainPreVisitor& aVisitor) {
|
||||
if (IsDisabledForEvents(aVisitor.mEvent)) {
|
||||
// Do not process any DOM events if the element is disabled
|
||||
aVisitor.mCanHandle = false;
|
||||
return;
|
||||
}
|
||||
|
||||
nsGenericHTMLFormElement::GetEventTargetParent(aVisitor);
|
||||
}
|
||||
|
||||
nsresult HTMLElement::BindToTree(BindContext& aContext, nsINode& aParent) {
|
||||
nsresult rv = nsGenericHTMLFormElement::BindToTree(aContext, aParent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -179,6 +190,14 @@ void HTMLElement::UpdateFormOwner() {
|
|||
UpdateBarredFromConstraintValidation();
|
||||
}
|
||||
|
||||
bool HTMLElement::IsDisabledForEvents(WidgetEvent* aEvent) {
|
||||
if (IsFormAssociatedElement()) {
|
||||
return IsElementDisabledForEvents(aEvent, GetPrimaryFrame());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult HTMLElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
const nsAttrValue* aOldValue,
|
||||
|
|
|
@ -20,6 +20,9 @@ class HTMLElement final : public nsGenericHTMLFormElement {
|
|||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLElement,
|
||||
nsGenericHTMLFormElement)
|
||||
|
||||
// EventTarget
|
||||
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||
|
||||
// nsINode
|
||||
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
|
||||
|
||||
|
@ -36,6 +39,7 @@ class HTMLElement final : public nsGenericHTMLFormElement {
|
|||
// https://html.spec.whatwg.org/multipage/custom-elements.html#dom-attachinternals
|
||||
already_AddRefed<mozilla::dom::ElementInternals> AttachInternals(
|
||||
ErrorResult& aRv) override;
|
||||
bool IsDisabledForEvents(WidgetEvent* aEvent) override;
|
||||
|
||||
// nsGenericHTMLFormElement
|
||||
bool IsFormAssociatedElement() const override;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<meta name="timeout" content="long">
|
||||
<link rel=author href="mailto:jarhar@chromium.org">
|
||||
<link rel=help href="https://github.com/whatwg/html/issues/2368">
|
||||
<link rel=help href="https://github.com/whatwg/html/issues/5886">
|
||||
|
@ -9,37 +10,48 @@
|
|||
<script src="/resources/testdriver-actions.js"></script>
|
||||
|
||||
<div id=targetparent>
|
||||
<button id=target disabled>
|
||||
<button disabled>
|
||||
hello world
|
||||
<span style="border: 1px solid black" id=targetchild>child</span>
|
||||
<span style="border: 1px solid black">child</span>
|
||||
</button>
|
||||
<my-control disabled>
|
||||
hello world
|
||||
<span style="border: 1px solid black">child</span>
|
||||
</my-control>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
customElements.define('my-control', class extends HTMLElement {
|
||||
static get formAssociated() { return true; }
|
||||
});
|
||||
|
||||
['mousedown', 'mouseup', 'pointerdown', 'pointerup', 'click'].forEach(eventName => {
|
||||
[true, false].forEach(clickChildElement => {
|
||||
promise_test(async () => {
|
||||
let parentReceivedEvent = false;
|
||||
targetparent.addEventListener(eventName, () => parentReceivedEvent = true);
|
||||
for (const target of targetparent.children) {
|
||||
promise_test(async () => {
|
||||
let parentReceivedEvent = false;
|
||||
targetparent.addEventListener(eventName, () => parentReceivedEvent = true);
|
||||
|
||||
let targetReceivedEvent = false;
|
||||
target.addEventListener(eventName, () => targetReceivedEvent = true);
|
||||
let targetReceivedEvent = false;
|
||||
target.addEventListener(eventName, () => targetReceivedEvent = true);
|
||||
|
||||
let childReceivedEvent = false;
|
||||
targetchild.addEventListener(eventName, () => childReceivedEvent = true);
|
||||
let childReceivedEvent = false;
|
||||
let targetchild = target.firstElementChild;
|
||||
targetchild.addEventListener(eventName, () => childReceivedEvent = true);
|
||||
|
||||
await test_driver.click(clickChildElement ? targetchild : target);
|
||||
await test_driver.click(clickChildElement ? targetchild : target);
|
||||
|
||||
const parentShouldReceiveEvents = eventName.startsWith('pointer');
|
||||
assert_equals(parentReceivedEvent, parentShouldReceiveEvents,
|
||||
`parent element received ${eventName} events`);
|
||||
const parentShouldReceiveEvents = eventName.startsWith('pointer');
|
||||
assert_equals(parentReceivedEvent, parentShouldReceiveEvents,
|
||||
`parent element received ${eventName} events`);
|
||||
|
||||
const targetShouldReceiveEvents = eventName.startsWith('pointer');
|
||||
assert_equals(targetReceivedEvent, targetShouldReceiveEvents,
|
||||
`target element received ${eventName} events`);
|
||||
assert_equals(childReceivedEvent, clickChildElement,
|
||||
`child element received ${eventName} events`);
|
||||
}, `Testing ${eventName} events when clicking ${clickChildElement ? 'child of ' : ''}disabled form controls.`);
|
||||
const targetShouldReceiveEvents = eventName.startsWith('pointer');
|
||||
assert_equals(targetReceivedEvent, targetShouldReceiveEvents,
|
||||
`target element received ${eventName} events`);
|
||||
assert_equals(childReceivedEvent, clickChildElement,
|
||||
`child element received ${eventName} events`);
|
||||
}, `Testing ${eventName} events when clicking ${clickChildElement ? 'child of ' : ''}disabled ${target.localName}.`);
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -47,9 +47,15 @@
|
|||
<input disabled type="time">
|
||||
<input disabled type="url">
|
||||
<input disabled type="week">
|
||||
<my-control disabled>Text</my-control>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
customElements.define('my-control', class extends HTMLElement {
|
||||
static get formAssociated() { return true; }
|
||||
get disabled() { return this.hasAttribute("disabled"); }
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Element} element
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче