michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: "use strict"; michael@0: michael@0: module.metadata = { michael@0: "stability": "unstable" michael@0: }; michael@0: michael@0: // Utility function that returns copy of the given `text` with last character michael@0: // removed if it is `"s"`. michael@0: function singularify(text) { michael@0: return text[text.length - 1] === "s" ? text.substr(0, text.length - 1) : text; michael@0: } michael@0: michael@0: // Utility function that takes event type, argument is passed to michael@0: // `document.createEvent` and returns name of the initializer method of the michael@0: // given event. Please note that there are some event types whose initializer michael@0: // methods can't be guessed by this function. For more details see following michael@0: // link: https://developer.mozilla.org/En/DOM/Document.createEvent michael@0: function getInitializerName(category) { michael@0: return "init" + singularify(category); michael@0: } michael@0: michael@0: /** michael@0: * Registers an event `listener` on a given `element`, that will be called michael@0: * when events of specified `type` is dispatched on the `element`. michael@0: * @param {Element} element michael@0: * Dom element to register listener on. michael@0: * @param {String} type michael@0: * A string representing the michael@0: * [event type](https://developer.mozilla.org/en/DOM/event.type) to michael@0: * listen for. michael@0: * @param {Function} listener michael@0: * Function that is called whenever an event of the specified `type` michael@0: * occurs. michael@0: * @param {Boolean} capture michael@0: * If true, indicates that the user wishes to initiate capture. After michael@0: * initiating capture, all events of the specified type will be dispatched michael@0: * to the registered listener before being dispatched to any `EventTarget`s michael@0: * beneath it in the DOM tree. Events which are bubbling upward through michael@0: * the tree will not trigger a listener designated to use capture. michael@0: * See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow) michael@0: * for a detailed explanation. michael@0: */ michael@0: function on(element, type, listener, capture) { michael@0: // `capture` defaults to `false`. michael@0: capture = capture || false; michael@0: element.addEventListener(type, listener, capture); michael@0: } michael@0: exports.on = on; michael@0: michael@0: /** michael@0: * Registers an event `listener` on a given `element`, that will be called michael@0: * only once, next time event of specified `type` is dispatched on the michael@0: * `element`. michael@0: * @param {Element} element michael@0: * Dom element to register listener on. michael@0: * @param {String} type michael@0: * A string representing the michael@0: * [event type](https://developer.mozilla.org/en/DOM/event.type) to michael@0: * listen for. michael@0: * @param {Function} listener michael@0: * Function that is called whenever an event of the specified `type` michael@0: * occurs. michael@0: * @param {Boolean} capture michael@0: * If true, indicates that the user wishes to initiate capture. After michael@0: * initiating capture, all events of the specified type will be dispatched michael@0: * to the registered listener before being dispatched to any `EventTarget`s michael@0: * beneath it in the DOM tree. Events which are bubbling upward through michael@0: * the tree will not trigger a listener designated to use capture. michael@0: * See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow) michael@0: * for a detailed explanation. michael@0: */ michael@0: function once(element, type, listener, capture) { michael@0: on(element, type, function selfRemovableListener(event) { michael@0: removeListener(element, type, selfRemovableListener, capture); michael@0: listener.apply(this, arguments); michael@0: }, capture); michael@0: } michael@0: exports.once = once; michael@0: michael@0: /** michael@0: * Unregisters an event `listener` on a given `element` for the events of the michael@0: * specified `type`. michael@0: * michael@0: * @param {Element} element michael@0: * Dom element to unregister listener from. michael@0: * @param {String} type michael@0: * A string representing the michael@0: * [event type](https://developer.mozilla.org/en/DOM/event.type) to michael@0: * listen for. michael@0: * @param {Function} listener michael@0: * Function that is called whenever an event of the specified `type` michael@0: * occurs. michael@0: * @param {Boolean} capture michael@0: * If true, indicates that the user wishes to initiate capture. After michael@0: * initiating capture, all events of the specified type will be dispatched michael@0: * to the registered listener before being dispatched to any `EventTarget`s michael@0: * beneath it in the DOM tree. Events which are bubbling upward through michael@0: * the tree will not trigger a listener designated to use capture. michael@0: * See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow) michael@0: * for a detailed explanation. michael@0: */ michael@0: function removeListener(element, type, listener, capture) { michael@0: element.removeEventListener(type, listener, capture); michael@0: } michael@0: exports.removeListener = removeListener; michael@0: michael@0: /** michael@0: * Emits event of the specified `type` and `category` on the given `element`. michael@0: * Specified `settings` are used to initialize event before dispatching it. michael@0: * @param {Element} element michael@0: * Dom element to dispatch event on. michael@0: * @param {String} type michael@0: * A string representing the michael@0: * [event type](https://developer.mozilla.org/en/DOM/event.type). michael@0: * @param {Object} options michael@0: * Options object containing following properties: michael@0: * - `category`: String passed to the `document.createEvent`. Option is michael@0: * optional and defaults to "UIEvents". michael@0: * - `initializer`: If passed it will be used as name of the method used michael@0: * to initialize event. If omitted name will be generated from the michael@0: * `category` field by prefixing it with `"init"` and removing last michael@0: * character if it matches `"s"`. michael@0: * - `settings`: Array of settings that are forwarded to the event michael@0: * initializer after firs `type` argument. michael@0: * @see https://developer.mozilla.org/En/DOM/Document.createEvent michael@0: */ michael@0: function emit(element, type, { category, initializer, settings }) { michael@0: category = category || "UIEvents"; michael@0: initializer = initializer || getInitializerName(category); michael@0: let document = element.ownerDocument; michael@0: let event = document.createEvent(category); michael@0: event[initializer].apply(event, [type].concat(settings)); michael@0: element.dispatchEvent(event); michael@0: }; michael@0: exports.emit = emit;