@enact/core
Version:
Enact is an open source JavaScript framework containing everything you need to create a fast, scalable mobile or web application.
162 lines (153 loc) • 4.43 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.setDefaultTargetById = exports.once = exports.on = exports.off = void 0;
var _curry = _interopRequireDefault(require("ramda/src/curry"));
var _listeners = require("./listeners");
function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
/**
* Provides methods to add and remove global event listeners.
*
* @module core/dispatcher
* @exports off
* @exports on
* @exports once
*/
var defaultTarget = typeof document === 'object' && document;
var rootId;
/*
* Sets a selector for the default target. If no selector is set, `document` is the default target.
*
* @function
* @param {String} id Node id of the default target
*
* @returns {undefined}
* @memberof core/dispatcher
* @private
*/
var setDefaultTargetById = exports.setDefaultTargetById = function setDefaultTargetById(id) {
defaultTarget = typeof document === 'object' && document.querySelector('#' + id) || defaultTarget;
rootId = id;
};
/*
* Checks if the default target of `document` exists before returning it, otherwise returns `false`.
* If the default target is falsy and the stored id of the root exists, it tries to find the
* default target based on the id.
*
* @function
*
* @returns {Node|Boolean}
* @memberof core/dispatcher
* @private
*/
var getDefaultTarget = function getDefaultTarget() {
if (!defaultTarget && rootId) {
setDefaultTargetById(rootId);
}
return defaultTarget;
};
/*
* Wraps event callbacks with a try-catch block to prevent unrelated code from blocking.
*
* @function
* @param {Event} ev Event payload
* @param {Function} fn Event callback
*
* @returns {undefined}
* @memberof core/dispatcher
* @private
*/
var invoker = (0, _curry["default"])(function (ev, fn) {
try {
fn(ev);
} catch (e) {
// eslint-disable-next-line no-console
console.error("A ".concat(e.name, " occurred during event handling with the message '").concat(e.message, "'"));
}
});
/*
* Dispatches an event to the registered handlers.
*
* @function
* @param {Event} ev Event payload
*
* @returns {undefined}
* @memberof core/dispatcher
* @private
*/
var dispatcher = function dispatcher(ev) {
var name = ev.type;
var listeners = (0, _listeners.getListeners)(ev.currentTarget, name);
if (listeners) {
var inv = invoker(ev);
listeners.forEach(inv);
}
};
/**
* Adds a new global event listener. Duplicate event handlers will be discarded.
*
* @function
* @param {String} name Event name
* @param {Function} fn Event handler
* @param {Node} [target='document'] Event listener target
*
* @returns {undefined}
* @memberof core/dispatcher
* @public
*/
var on = exports.on = function on(name, fn) {
var target = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getDefaultTarget();
if (target) {
var added = (0, _listeners.addListener)(target, name, fn);
if (added && (0, _listeners.getListeners)(target, name).length === 1) {
target.addEventListener(name, dispatcher);
}
}
};
/**
* Removes a global event listener.
*
* @function
* @param {String} name Event name
* @param {Function} fn Event handler
* @param {Node} [target=`document`] Event listener target
*
* @returns {undefined}
* @memberof core/dispatcher
* @public
*/
var off = exports.off = function off(name, fn) {
var target = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getDefaultTarget();
if (target) {
var listeners = (0, _listeners.getListeners)(target, name);
var index = listeners.indexOf(fn);
if (index >= 0) {
listeners.splice(index, 1);
if (listeners.length === 0) {
target.removeEventListener(name, dispatcher);
}
}
}
};
/**
* Adds a new global event listener that removes itself after handling one event.
*
* @function
* @param {String} name Event name
* @param {Function} fn Event handler
* @param {Node} [target] Event listener target
*
* @returns {Function} The single-use handler. To remove the handler manually, call
* the `off()` function with this as the 2nd parameter.
* @memberof core/dispatcher
* @public
*/
var once = exports.once = function once(name, fn, target) {
var _onceFn = function onceFn(ev) {
fn(ev);
off(name, _onceFn, target);
};
on(name, _onceFn, target);
return _onceFn;
};