summaryrefslogtreecommitdiffstats
path: root/toolkit/jetpack/sdk/dom
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2018-02-09 06:46:43 -0500
committerMatt A. Tobin <email@mattatobin.com>2018-02-09 06:46:43 -0500
commitac46df8daea09899ce30dc8fd70986e258c746bf (patch)
tree2750d3125fc253fd5b0671e4bd268eff1fd97296 /toolkit/jetpack/sdk/dom
parent8cecf8d5208f3945b35f879bba3015bb1a11bec6 (diff)
downloadUXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar
UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar.gz
UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar.lz
UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar.xz
UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.zip
Move Add-on SDK source to toolkit/jetpack
Diffstat (limited to 'toolkit/jetpack/sdk/dom')
-rw-r--r--toolkit/jetpack/sdk/dom/events-shimmed.js18
-rw-r--r--toolkit/jetpack/sdk/dom/events.js192
-rw-r--r--toolkit/jetpack/sdk/dom/events/keys.js63
3 files changed, 273 insertions, 0 deletions
diff --git a/toolkit/jetpack/sdk/dom/events-shimmed.js b/toolkit/jetpack/sdk/dom/events-shimmed.js
new file mode 100644
index 000000000..7a1727681
--- /dev/null
+++ b/toolkit/jetpack/sdk/dom/events-shimmed.js
@@ -0,0 +1,18 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+module.metadata = {
+ 'stability': 'unstable'
+};
+
+const events = require('./events.js');
+
+exports.emit = (element, type, obj) => events.emit(element, type, obj, true);
+exports.on = (element, type, listener, capture) => events.on(element, type, listener, capture, true);
+exports.once = (element, type, listener, capture) => events.once(element, type, listener, capture, true);
+exports.removeListener = (element, type, listener, capture) => events.removeListener(element, type, listener, capture, true);
+exports.removed = events.removed;
+exports.when = (element, eventName, capture) => events.when(element, eventName, capture ? capture : false, true);
diff --git a/toolkit/jetpack/sdk/dom/events.js b/toolkit/jetpack/sdk/dom/events.js
new file mode 100644
index 000000000..502d2350f
--- /dev/null
+++ b/toolkit/jetpack/sdk/dom/events.js
@@ -0,0 +1,192 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+module.metadata = {
+ "stability": "unstable"
+};
+
+const { Cu } = require("chrome");
+const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
+
+// Utility function that returns copy of the given `text` with last character
+// removed if it is `"s"`.
+function singularify(text) {
+ return text[text.length - 1] === "s" ? text.substr(0, text.length - 1) : text;
+}
+
+// Utility function that takes event type, argument is passed to
+// `document.createEvent` and returns name of the initializer method of the
+// given event. Please note that there are some event types whose initializer
+// methods can't be guessed by this function. For more details see following
+// link: https://developer.mozilla.org/En/DOM/Document.createEvent
+function getInitializerName(category) {
+ return "init" + singularify(category);
+}
+
+/**
+ * Registers an event `listener` on a given `element`, that will be called
+ * when events of specified `type` is dispatched on the `element`.
+ * @param {Element} element
+ * Dom element to register listener on.
+ * @param {String} type
+ * A string representing the
+ * [event type](https://developer.mozilla.org/en/DOM/event.type) to
+ * listen for.
+ * @param {Function} listener
+ * Function that is called whenever an event of the specified `type`
+ * occurs.
+ * @param {Boolean} capture
+ * If true, indicates that the user wishes to initiate capture. After
+ * initiating capture, all events of the specified type will be dispatched
+ * to the registered listener before being dispatched to any `EventTarget`s
+ * beneath it in the DOM tree. Events which are bubbling upward through
+ * the tree will not trigger a listener designated to use capture.
+ * See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
+ * for a detailed explanation.
+ */
+function on(element, type, listener, capture, shimmed = false) {
+ // `capture` defaults to `false`.
+ capture = capture || false;
+ if (shimmed) {
+ element.addEventListener(type, listener, capture);
+ } else {
+ ShimWaiver.getProperty(element, "addEventListener")(type, listener, capture);
+ }
+}
+exports.on = on;
+
+/**
+ * Registers an event `listener` on a given `element`, that will be called
+ * only once, next time event of specified `type` is dispatched on the
+ * `element`.
+ * @param {Element} element
+ * Dom element to register listener on.
+ * @param {String} type
+ * A string representing the
+ * [event type](https://developer.mozilla.org/en/DOM/event.type) to
+ * listen for.
+ * @param {Function} listener
+ * Function that is called whenever an event of the specified `type`
+ * occurs.
+ * @param {Boolean} capture
+ * If true, indicates that the user wishes to initiate capture. After
+ * initiating capture, all events of the specified type will be dispatched
+ * to the registered listener before being dispatched to any `EventTarget`s
+ * beneath it in the DOM tree. Events which are bubbling upward through
+ * the tree will not trigger a listener designated to use capture.
+ * See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
+ * for a detailed explanation.
+ */
+function once(element, type, listener, capture, shimmed = false) {
+ on(element, type, function selfRemovableListener(event) {
+ removeListener(element, type, selfRemovableListener, capture, shimmed);
+ listener.apply(this, arguments);
+ }, capture, shimmed);
+}
+exports.once = once;
+
+/**
+ * Unregisters an event `listener` on a given `element` for the events of the
+ * specified `type`.
+ *
+ * @param {Element} element
+ * Dom element to unregister listener from.
+ * @param {String} type
+ * A string representing the
+ * [event type](https://developer.mozilla.org/en/DOM/event.type) to
+ * listen for.
+ * @param {Function} listener
+ * Function that is called whenever an event of the specified `type`
+ * occurs.
+ * @param {Boolean} capture
+ * If true, indicates that the user wishes to initiate capture. After
+ * initiating capture, all events of the specified type will be dispatched
+ * to the registered listener before being dispatched to any `EventTarget`s
+ * beneath it in the DOM tree. Events which are bubbling upward through
+ * the tree will not trigger a listener designated to use capture.
+ * See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
+ * for a detailed explanation.
+ */
+function removeListener(element, type, listener, capture, shimmed = false) {
+ if (shimmed) {
+ element.removeEventListener(type, listener, capture);
+ } else {
+ ShimWaiver.getProperty(element, "removeEventListener")(type, listener, capture);
+ }
+}
+exports.removeListener = removeListener;
+
+/**
+ * Emits event of the specified `type` and `category` on the given `element`.
+ * Specified `settings` are used to initialize event before dispatching it.
+ * @param {Element} element
+ * Dom element to dispatch event on.
+ * @param {String} type
+ * A string representing the
+ * [event type](https://developer.mozilla.org/en/DOM/event.type).
+ * @param {Object} options
+ * Options object containing following properties:
+ * - `category`: String passed to the `document.createEvent`. Option is
+ * optional and defaults to "UIEvents".
+ * - `initializer`: If passed it will be used as name of the method used
+ * to initialize event. If omitted name will be generated from the
+ * `category` field by prefixing it with `"init"` and removing last
+ * character if it matches `"s"`.
+ * - `settings`: Array of settings that are forwarded to the event
+ * initializer after firs `type` argument.
+ * @see https://developer.mozilla.org/En/DOM/Document.createEvent
+ */
+function emit(element, type, { category, initializer, settings }, shimmed = false) {
+ category = category || "UIEvents";
+ initializer = initializer || getInitializerName(category);
+ let document = element.ownerDocument;
+ let event = document.createEvent(category);
+ event[initializer].apply(event, [type].concat(settings));
+ if (shimmed) {
+ element.dispatchEvent(event);
+ } else {
+ ShimWaiver.getProperty(element, "dispatchEvent")(event);
+ }
+};
+exports.emit = emit;
+
+// Takes DOM `element` and returns promise which is resolved
+// when given element is removed from it's parent node.
+const removed = element => {
+ return new Promise(resolve => {
+ const { MutationObserver } = element.ownerDocument.defaultView;
+ const observer = new MutationObserver(mutations => {
+ for (let mutation of mutations) {
+ for (let node of mutation.removedNodes || []) {
+ if (node === element) {
+ observer.disconnect();
+ resolve(element);
+ }
+ }
+ }
+ });
+ observer.observe(element.parentNode, {childList: true});
+ });
+};
+exports.removed = removed;
+
+const when = (element, eventName, capture=false, shimmed=false) => new Promise(resolve => {
+ const listener = event => {
+ if (shimmed) {
+ element.removeEventListener(eventName, listener, capture);
+ } else {
+ ShimWaiver.getProperty(element, "removeEventListener")(eventName, listener, capture);
+ }
+ resolve(event);
+ };
+
+ if (shimmed) {
+ element.addEventListener(eventName, listener, capture);
+ } else {
+ ShimWaiver.getProperty(element, "addEventListener")(eventName, listener, capture);
+ }
+});
+exports.when = when;
diff --git a/toolkit/jetpack/sdk/dom/events/keys.js b/toolkit/jetpack/sdk/dom/events/keys.js
new file mode 100644
index 000000000..e6f1483a2
--- /dev/null
+++ b/toolkit/jetpack/sdk/dom/events/keys.js
@@ -0,0 +1,63 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+module.metadata = {
+ "stability": "unstable"
+};
+
+const { emit } = require("../events");
+const { getCodeForKey, toJSON } = require("../../keyboard/utils");
+const { has } = require("../../util/array");
+const { isString } = require("../../lang/type");
+
+const INITIALIZER = "initKeyEvent";
+const CATEGORY = "KeyboardEvent";
+
+function Options(options) {
+ if (!isString(options))
+ return options;
+
+ var { key, modifiers } = toJSON(options);
+ return {
+ key: key,
+ control: has(modifiers, "control"),
+ alt: has(modifiers, "alt"),
+ shift: has(modifiers, "shift"),
+ meta: has(modifiers, "meta")
+ };
+}
+
+var keyEvent = exports.keyEvent = function keyEvent(element, type, options) {
+
+ emit(element, type, {
+ initializer: INITIALIZER,
+ category: CATEGORY,
+ settings: [
+ !("bubbles" in options) || options.bubbles !== false,
+ !("cancelable" in options) || options.cancelable !== false,
+ "window" in options && options.window ? options.window : null,
+ "control" in options && !!options.control,
+ "alt" in options && !!options.alt,
+ "shift" in options && !!options.shift,
+ "meta" in options && !!options.meta,
+ getCodeForKey(options.key) || 0,
+ options.key.length === 1 ? options.key.charCodeAt(0) : 0
+ ]
+ });
+}
+
+exports.keyDown = function keyDown(element, options) {
+ keyEvent(element, "keydown", Options(options));
+};
+
+exports.keyUp = function keyUp(element, options) {
+ keyEvent(element, "keyup", Options(options));
+};
+
+exports.keyPress = function keyPress(element, options) {
+ keyEvent(element, "keypress", Options(options));
+};
+