(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (factory((global.MinDom = {}))); }(this, (function (exports) { 'use strict'; /** * 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; } var indexOf = [].indexOf; var indexof = function(arr, obj){ if (indexOf) return arr.indexOf(obj); for (var i = 0; i < arr.length; ++i) { if (arr[i] === obj) return i; } return -1; }; /** * Taken from https://github.com/component/classes * * Without the component bits. */ /** * Whitespace regexp. */ var re = /\s+/; /** * toString reference. */ var 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) { // classList if (this.list) { this.list.add(name); return this; } // fallback var arr = this.array(); var i = indexof(arr, name); if (!~i) arr.push(name); this.el.className = arr.join(' '); 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); } // classList if (this.list) { this.list.remove(name); return this; } // fallback var arr = this.array(); var i = indexof(arr, name); if (~i) arr.splice(i, 1); this.el.className = arr.join(' '); return this; }; /** * Remove all classes matching `re`. * * @param {RegExp} re * @return {ClassList} * @api private */ ClassList.prototype.removeMatching = function (re) { var arr = this.array(); for (var 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) { // classList if (this.list) { 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; } // fallback if ('undefined' !== typeof force) { if (!force) { this.remove(name); } else { this.add(name); } } else { if (this.has(name)) { this.remove(name); } else { this.add(name); } } return this; }; /** * Return an array of classes. * * @return {Array} * @api public */ ClassList.prototype.array = function () { var className = this.el.getAttribute('class') || ''; var str = className.replace(/^\s+|\s+$/g, ''); var arr = str.split(re); if ('' === arr[0]) arr.shift(); return arr; }; /** * Check if class `name` is present. * * @param {String} name * @return {ClassList} * @api public */ ClassList.prototype.has = ClassList.prototype.contains = function (name) { return this.list ? this.list.contains(name) : !!~indexof(this.array(), name); }; /** * Remove all children from the given element. */ function clear(el) { var c; while (el.childNodes.length) { c = el.childNodes[0]; el.removeChild(c); } return el; } var proto = typeof Element !== 'undefined' ? Element.prototype : {}; var vendor = proto.matches || proto.matchesSelector || proto.webkitMatchesSelector || proto.mozMatchesSelector || proto.msMatchesSelector || proto.oMatchesSelector; var matchesSelector = match; /** * Match `el` to `selector`. * * @param {Element} el * @param {String} selector * @return {Boolean} * @api public */ function match(el, selector) { if (!el || el.nodeType !== 1) return false; if (vendor) return vendor.call(el, selector); var nodes = el.parentNode.querySelectorAll(selector); for (var i = 0; i < nodes.length; i++) { if (nodes[i] == el) return true; } return false; } /** * Closest * * @param {Element} el * @param {String} selector * @param {Boolean} checkYourSelf (optional) */ function closest (element, selector, checkYourSelf) { var currentElem = checkYourSelf ? element : element.parentNode; while (currentElem && currentElem.nodeType !== document.DOCUMENT_NODE && currentElem.nodeType !== document.DOCUMENT_FRAGMENT_NODE) { if (matchesSelector(currentElem, selector)) { return currentElem; } currentElem = currentElem.parentNode; } return matchesSelector(currentElem, selector) ? currentElem : null; } var bind = window.addEventListener ? 'addEventListener' : 'attachEvent', unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent', prefix = bind !== '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 = function(el, type, fn, capture){ el[bind](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 = function(el, type, fn, capture){ el[unbind](prefix + type, fn, capture || false); return fn; }; var componentEvent = { bind: bind_1, unbind: unbind_1 }; /** * 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$1(el, selector, type, fn, capture) { if (forceCaptureEvents.indexOf(type) !== -1) { capture = true; } return componentEvent.bind(el, type, function (e) { var target = e.target || e.srcElement; e.delegateTarget = closest(target, selector, true, el); 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$1(el, type, fn, capture) { if (forceCaptureEvents.indexOf(type) !== -1) { capture = true; } return componentEvent.unbind(el, type, fn, capture); } var delegate = { bind: bind$1, unbind: unbind$1 }; /** * Expose `parse`. */ var domify = parse; /** * Tests for browser support. */ var innerHTMLBug = false; var bugTestDiv; if (typeof document !== 'undefined') { bugTestDiv = document.createElement('div'); // Setup bugTestDiv.innerHTML = '
a'; // Make sure that link elements get serialized correctly by innerHTML // This requires a wrapper element in IE innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length; bugTestDiv = undefined; } /** * Wrap map from jquery. */ var map = { legend: [1, '
', '
'], tr: [2, '', '
'], col: [2, '', '
'], // for script/link/style tags to work in IE6-8, you have to wrap // in a div with a non-whitespace character in front, ha! _default: innerHTMLBug ? [1, 'X
', '
'] : [0, '', ''] }; map.td = map.th = [3, '', '
']; map.option = map.optgroup = [1, '']; map.thead = map.tbody = map.colgroup = map.caption = map.tfoot = [1, '', '
']; map.polyline = map.ellipse = map.polygon = map.circle = map.text = map.line = map.path = map.rect = map.g = [1, '','']; /** * Parse `html` and return a DOM Node instance, which could be a TextNode, * HTML DOM Node of some kind (
for example), or a DocumentFragment * instance, depending on the contents of the `html` string. * * @param {String} html - HTML string to "domify" * @param {Document} doc - The `document` instance to create the Node for * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance * @api private */ function parse(html, doc) { if ('string' != typeof html) throw new TypeError('String expected'); // default to the global `document` object if (!doc) doc = document; // tag name var m = /<([\w:]+)/.exec(html); if (!m) return doc.createTextNode(html); html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace var tag = m[1]; // body support if (tag == 'body') { var el = doc.createElement('html'); el.innerHTML = html; return el.removeChild(el.lastChild); } // wrap map var wrap = map[tag] || map._default; var depth = wrap[0]; var prefix = wrap[1]; var suffix = wrap[2]; var el = doc.createElement('div'); el.innerHTML = prefix + html + suffix; while (depth--) el = el.lastChild; // one element if (el.firstChild == el.lastChild) { return el.removeChild(el.firstChild); } // several elements var fragment = doc.createDocumentFragment(); while (el.firstChild) { fragment.appendChild(el.removeChild(el.firstChild)); } return fragment; } 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); } exports.attr = attr; exports.classes = classes; exports.clear = clear; exports.closest = closest; exports.delegate = delegate; exports.domify = domify; exports.event = componentEvent; exports.matches = matchesSelector; exports.query = query; exports.queryAll = all; exports.remove = remove; Object.defineProperty(exports, '__esModule', { value: true }); })));