| <!DOCTYPE html> |
| <title>GlobalEventHandlers</title> |
| <link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me"> |
| <link rel="help" href="https://html.spec.whatwg.org/multipage/#globaleventhandlers"> |
| <link rel="help" href="https://html.spec.whatwg.org/multipage/#event-handler-idl-attributes"> |
| <link rel="help" href="https://html.spec.whatwg.org/multipage/#event-handler-content-attributes"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/resources/WebIDLParser.js"></script> |
| |
| <script> |
| "use strict"; |
| |
| // The prefixed animation events are special; their event types are |
| // camel-case. |
| const prefixedAnimationAttributeToEventType = new Map([ |
| ["webkitanimationend", "webkitAnimationEnd"], |
| ["webkitanimationiteration", "webkitAnimationIteration"], |
| ["webkitanimationstart", "webkitAnimationStart"], |
| ["webkittransitionend", "webkitTransitionEnd"], |
| ]); |
| |
| setup({ explicit_done: true }); |
| |
| fetch("/interfaces/html.idl").then(res => res.text()).then(htmlIDL => { |
| const parsedHTMLIDL = WebIDL2.parse(htmlIDL); |
| const globalEventHandlers = parsedHTMLIDL.find(idl => idl.name === "GlobalEventHandlers"); |
| |
| // onerror is too special |
| const names = globalEventHandlers.members.map(member => member.name).filter(name => name !== "onerror"); |
| |
| for (const name of names) { |
| const withoutOn = name.substring(2); |
| |
| test(() => { |
| for (const location of [window, HTMLElement.prototype, SVGElement.prototype, Document.prototype]) { |
| assert_true(location.hasOwnProperty(name), |
| `${location.constructor.name} has an own property named "${name}"`); |
| } |
| assert_false(name in Element.prototype, `Element.prototype must not contain a "${name}" property`); |
| }, `${name}: must be on the appropriate locations for GlobalEventHandlers`); |
| |
| test(() => { |
| const htmlElement = document.createElement("span"); |
| const svgElement = document.createElementNS("http://www.w3.org/2000/svg", "g"); |
| |
| for (var location of [window, htmlElement, svgElement, document]) { |
| assert_equals(location[name], null, |
| `The default value of the property is null for a ${location.constructor.name} instance`); |
| } |
| }, `${name}: the default value must be null`); |
| |
| test(() => { |
| const el = document.createElement("div"); |
| el.setAttribute(name, `window.${name}Happened = true;`); |
| const compiledHandler = el[name]; |
| |
| assert_equals(typeof compiledHandler, "function", `The ${name} property must be a function`); |
| compiledHandler(); |
| assert_true(window[name + "Happened"], "Calling the handler must run the code"); |
| }, `${name}: the content attribute must be compiled into a function as the corresponding property`); |
| |
| test(() => { |
| const el = document.createElement("div"); |
| el.setAttribute(name, `window.${name}Happened2 = true;`); |
| |
| let eventType = withoutOn; |
| if (prefixedAnimationAttributeToEventType.has(eventType)) { |
| eventType = prefixedAnimationAttributeToEventType.get(eventType); |
| } |
| el.dispatchEvent(new Event(eventType)); |
| |
| assert_true(window[name + "Happened2"], "Dispatching an event must run the code"); |
| }, `${name}: the content attribute must execute when an event is dispatched`); |
| |
| test(() => { |
| const element = document.createElement("meta"); |
| element[name] = e => { |
| assert_equals(e.currentTarget, element, "The event must be fired at the <meta> element"); |
| }; |
| |
| element.dispatchEvent(new Event(withoutOn)); |
| }, `${name}: dispatching an Event at a <meta> element must trigger element.${name}`); |
| } |
| |
| done(); |
| }); |
| </script> |