UNPKG

min-dom

Version:

A minimal dom utility toolbelt

377 lines (316 loc) 7.38 kB
import { forEach } from 'min-dash'; export { default as domify } from 'domify'; function _mergeNamespaces(n, m) { m.forEach(function (e) { e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) { if (k !== 'default' && !(k in n)) { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); }); return Object.freeze(n); } /** * Assigns style attributes in a style-src compliant way. * * @param {Element} element * @param {...Object} styleSources * * @return {Element} the element */ function assign(element, ...styleSources) { const target = element.style; forEach(styleSources, function(style) { if (!style) { return; } forEach(style, function(value, key) { target[key] = value; }); }); return element; } /** * Set attribute `name` to `val`, or get attr `name`. * * @param {Element} el * @param {String} name * @param {String} [val] * @api public */ function attr(el, name, val) { // get if (arguments.length == 2) { return el.getAttribute(name); } // remove if (val === null) { return el.removeAttribute(name); } // set el.setAttribute(name, val); return el; } /** * Taken from https://github.com/component/classes * * Without the component bits. */ /** * toString reference. */ const toString = Object.prototype.toString; /** * Wrap `el` in a `ClassList`. * * @param {Element} el * @return {ClassList} * @api public */ function classes(el) { return new ClassList(el); } /** * Initialize a new ClassList for `el`. * * @param {Element} el * @api private */ function ClassList(el) { if (!el || !el.nodeType) { throw new Error('A DOM element reference is required'); } this.el = el; this.list = el.classList; } /** * Add class `name` if not already present. * * @param {String} name * @return {ClassList} * @api public */ ClassList.prototype.add = function(name) { this.list.add(name); return this; }; /** * Remove class `name` when present, or * pass a regular expression to remove * any which match. * * @param {String|RegExp} name * @return {ClassList} * @api public */ ClassList.prototype.remove = function(name) { if ('[object RegExp]' == toString.call(name)) { return this.removeMatching(name); } this.list.remove(name); return this; }; /** * Remove all classes matching `re`. * * @param {RegExp} re * @return {ClassList} * @api private */ ClassList.prototype.removeMatching = function(re) { const arr = this.array(); for (let i = 0; i < arr.length; i++) { if (re.test(arr[i])) { this.remove(arr[i]); } } return this; }; /** * Toggle class `name`, can force state via `force`. * * For browsers that support classList, but do not support `force` yet, * the mistake will be detected and corrected. * * @param {String} name * @param {Boolean} force * @return {ClassList} * @api public */ ClassList.prototype.toggle = function(name, force) { if ('undefined' !== typeof force) { if (force !== this.list.toggle(name, force)) { this.list.toggle(name); // toggle again to correct } } else { this.list.toggle(name); } return this; }; /** * Return an array of classes. * * @return {Array} * @api public */ ClassList.prototype.array = function() { return Array.from(this.list); }; /** * Check if class `name` is present. * * @param {String} name * @return {ClassList} * @api public */ ClassList.prototype.has = ClassList.prototype.contains = function(name) { return this.list.contains(name); }; /** * Clear utility */ /** * Removes all children from the given element * * @param {Element} element * * @return {Element} the element (for chaining) */ function clear(element) { var child; while ((child = element.firstChild)) { element.removeChild(child); } return element; } /** * Closest * * @param {Element} el * @param {string} selector * @param {boolean} checkYourSelf (optional) */ function closest(element, selector, checkYourSelf) { var actualElement = checkYourSelf ? element : element.parentNode; return actualElement && typeof actualElement.closest === 'function' && actualElement.closest(selector) || null; } var componentEvent = {}; var bind$1, unbind$1, prefix; function detect () { bind$1 = window.addEventListener ? 'addEventListener' : 'attachEvent'; unbind$1 = window.removeEventListener ? 'removeEventListener' : 'detachEvent'; prefix = bind$1 !== 'addEventListener' ? 'on' : ''; } /** * Bind `el` event `type` to `fn`. * * @param {Element} el * @param {String} type * @param {Function} fn * @param {Boolean} capture * @return {Function} * @api public */ var bind_1 = componentEvent.bind = function(el, type, fn, capture){ if (!bind$1) detect(); el[bind$1](prefix + type, fn, capture || false); return fn; }; /** * Unbind `el` event `type`'s callback `fn`. * * @param {Element} el * @param {String} type * @param {Function} fn * @param {Boolean} capture * @return {Function} * @api public */ var unbind_1 = componentEvent.unbind = function(el, type, fn, capture){ if (!unbind$1) detect(); el[unbind$1](prefix + type, fn, capture || false); return fn; }; var event = /*#__PURE__*/_mergeNamespaces({ __proto__: null, bind: bind_1, default: componentEvent, unbind: unbind_1 }, [componentEvent]); /** * Module dependencies. */ /** * Delegate event `type` to `selector` * and invoke `fn(e)`. A callback function * is returned which may be passed to `.unbind()`. * * @param {Element} el * @param {String} selector * @param {String} type * @param {Function} fn * @param {Boolean} capture * @return {Function} * @api public */ // Some events don't bubble, so we want to bind to the capture phase instead // when delegating. var forceCaptureEvents = [ 'focus', 'blur' ]; function bind(el, selector, type, fn, capture) { if (forceCaptureEvents.indexOf(type) !== -1) { capture = true; } return event.bind(el, type, function(e) { var target = e.target || e.srcElement; e.delegateTarget = closest(target, selector, true); if (e.delegateTarget) { fn.call(el, e); } }, capture); } /** * Unbind event `type`'s callback `fn`. * * @param {Element} el * @param {String} type * @param {Function} fn * @param {Boolean} capture * @api public */ function unbind(el, type, fn, capture) { if (forceCaptureEvents.indexOf(type) !== -1) { capture = true; } return event.unbind(el, type, fn, capture); } var delegate = { bind, unbind }; /** * @param { HTMLElement } element * @param { String } selector * * @return { boolean } */ function matches(element, selector) { return element && typeof element.matches === 'function' && element.matches(selector) || false; } function query(selector, el) { el = el || document; return el.querySelector(selector); } function all(selector, el) { el = el || document; return el.querySelectorAll(selector); } function remove(el) { el.parentNode && el.parentNode.removeChild(el); } export { assign as assignStyle, attr, classes, clear, closest, delegate, event, matches, query, all as queryAll, remove }; //# sourceMappingURL=index.js.map