index.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. /**
  4. * Set attribute `name` to `val`, or get attr `name`.
  5. *
  6. * @param {Element} el
  7. * @param {String} name
  8. * @param {String} [val]
  9. * @api public
  10. */
  11. function attr(el, name, val) {
  12. // get
  13. if (arguments.length == 2) {
  14. return el.getAttribute(name);
  15. }
  16. // remove
  17. if (val === null) {
  18. return el.removeAttribute(name);
  19. }
  20. // set
  21. el.setAttribute(name, val);
  22. return el;
  23. }
  24. var indexOf = [].indexOf;
  25. var indexof = function(arr, obj){
  26. if (indexOf) return arr.indexOf(obj);
  27. for (var i = 0; i < arr.length; ++i) {
  28. if (arr[i] === obj) return i;
  29. }
  30. return -1;
  31. };
  32. /**
  33. * Taken from https://github.com/component/classes
  34. *
  35. * Without the component bits.
  36. */
  37. /**
  38. * Whitespace regexp.
  39. */
  40. var re = /\s+/;
  41. /**
  42. * toString reference.
  43. */
  44. var toString = Object.prototype.toString;
  45. /**
  46. * Wrap `el` in a `ClassList`.
  47. *
  48. * @param {Element} el
  49. * @return {ClassList}
  50. * @api public
  51. */
  52. function classes(el) {
  53. return new ClassList(el);
  54. }
  55. /**
  56. * Initialize a new ClassList for `el`.
  57. *
  58. * @param {Element} el
  59. * @api private
  60. */
  61. function ClassList(el) {
  62. if (!el || !el.nodeType) {
  63. throw new Error('A DOM element reference is required');
  64. }
  65. this.el = el;
  66. this.list = el.classList;
  67. }
  68. /**
  69. * Add class `name` if not already present.
  70. *
  71. * @param {String} name
  72. * @return {ClassList}
  73. * @api public
  74. */
  75. ClassList.prototype.add = function (name) {
  76. // classList
  77. if (this.list) {
  78. this.list.add(name);
  79. return this;
  80. }
  81. // fallback
  82. var arr = this.array();
  83. var i = indexof(arr, name);
  84. if (!~i) arr.push(name);
  85. this.el.className = arr.join(' ');
  86. return this;
  87. };
  88. /**
  89. * Remove class `name` when present, or
  90. * pass a regular expression to remove
  91. * any which match.
  92. *
  93. * @param {String|RegExp} name
  94. * @return {ClassList}
  95. * @api public
  96. */
  97. ClassList.prototype.remove = function (name) {
  98. if ('[object RegExp]' == toString.call(name)) {
  99. return this.removeMatching(name);
  100. }
  101. // classList
  102. if (this.list) {
  103. this.list.remove(name);
  104. return this;
  105. }
  106. // fallback
  107. var arr = this.array();
  108. var i = indexof(arr, name);
  109. if (~i) arr.splice(i, 1);
  110. this.el.className = arr.join(' ');
  111. return this;
  112. };
  113. /**
  114. * Remove all classes matching `re`.
  115. *
  116. * @param {RegExp} re
  117. * @return {ClassList}
  118. * @api private
  119. */
  120. ClassList.prototype.removeMatching = function (re) {
  121. var arr = this.array();
  122. for (var i = 0; i < arr.length; i++) {
  123. if (re.test(arr[i])) {
  124. this.remove(arr[i]);
  125. }
  126. }
  127. return this;
  128. };
  129. /**
  130. * Toggle class `name`, can force state via `force`.
  131. *
  132. * For browsers that support classList, but do not support `force` yet,
  133. * the mistake will be detected and corrected.
  134. *
  135. * @param {String} name
  136. * @param {Boolean} force
  137. * @return {ClassList}
  138. * @api public
  139. */
  140. ClassList.prototype.toggle = function (name, force) {
  141. // classList
  142. if (this.list) {
  143. if ('undefined' !== typeof force) {
  144. if (force !== this.list.toggle(name, force)) {
  145. this.list.toggle(name); // toggle again to correct
  146. }
  147. } else {
  148. this.list.toggle(name);
  149. }
  150. return this;
  151. }
  152. // fallback
  153. if ('undefined' !== typeof force) {
  154. if (!force) {
  155. this.remove(name);
  156. } else {
  157. this.add(name);
  158. }
  159. } else {
  160. if (this.has(name)) {
  161. this.remove(name);
  162. } else {
  163. this.add(name);
  164. }
  165. }
  166. return this;
  167. };
  168. /**
  169. * Return an array of classes.
  170. *
  171. * @return {Array}
  172. * @api public
  173. */
  174. ClassList.prototype.array = function () {
  175. var className = this.el.getAttribute('class') || '';
  176. var str = className.replace(/^\s+|\s+$/g, '');
  177. var arr = str.split(re);
  178. if ('' === arr[0]) arr.shift();
  179. return arr;
  180. };
  181. /**
  182. * Check if class `name` is present.
  183. *
  184. * @param {String} name
  185. * @return {ClassList}
  186. * @api public
  187. */
  188. ClassList.prototype.has = ClassList.prototype.contains = function (name) {
  189. return this.list ? this.list.contains(name) : !!~indexof(this.array(), name);
  190. };
  191. /**
  192. * Remove all children from the given element.
  193. */
  194. function clear(el) {
  195. var c;
  196. while (el.childNodes.length) {
  197. c = el.childNodes[0];
  198. el.removeChild(c);
  199. }
  200. return el;
  201. }
  202. var proto = typeof Element !== 'undefined' ? Element.prototype : {};
  203. var vendor = proto.matches
  204. || proto.matchesSelector
  205. || proto.webkitMatchesSelector
  206. || proto.mozMatchesSelector
  207. || proto.msMatchesSelector
  208. || proto.oMatchesSelector;
  209. var matchesSelector = match;
  210. /**
  211. * Match `el` to `selector`.
  212. *
  213. * @param {Element} el
  214. * @param {String} selector
  215. * @return {Boolean}
  216. * @api public
  217. */
  218. function match(el, selector) {
  219. if (!el || el.nodeType !== 1) return false;
  220. if (vendor) return vendor.call(el, selector);
  221. var nodes = el.parentNode.querySelectorAll(selector);
  222. for (var i = 0; i < nodes.length; i++) {
  223. if (nodes[i] == el) return true;
  224. }
  225. return false;
  226. }
  227. /**
  228. * Closest
  229. *
  230. * @param {Element} el
  231. * @param {String} selector
  232. * @param {Boolean} checkYourSelf (optional)
  233. */
  234. function closest (element, selector, checkYourSelf) {
  235. var currentElem = checkYourSelf ? element : element.parentNode;
  236. while (currentElem && currentElem.nodeType !== document.DOCUMENT_NODE && currentElem.nodeType !== document.DOCUMENT_FRAGMENT_NODE) {
  237. if (matchesSelector(currentElem, selector)) {
  238. return currentElem;
  239. }
  240. currentElem = currentElem.parentNode;
  241. }
  242. return matchesSelector(currentElem, selector) ? currentElem : null;
  243. }
  244. var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
  245. unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
  246. prefix = bind !== 'addEventListener' ? 'on' : '';
  247. /**
  248. * Bind `el` event `type` to `fn`.
  249. *
  250. * @param {Element} el
  251. * @param {String} type
  252. * @param {Function} fn
  253. * @param {Boolean} capture
  254. * @return {Function}
  255. * @api public
  256. */
  257. var bind_1 = function(el, type, fn, capture){
  258. el[bind](prefix + type, fn, capture || false);
  259. return fn;
  260. };
  261. /**
  262. * Unbind `el` event `type`'s callback `fn`.
  263. *
  264. * @param {Element} el
  265. * @param {String} type
  266. * @param {Function} fn
  267. * @param {Boolean} capture
  268. * @return {Function}
  269. * @api public
  270. */
  271. var unbind_1 = function(el, type, fn, capture){
  272. el[unbind](prefix + type, fn, capture || false);
  273. return fn;
  274. };
  275. var componentEvent = {
  276. bind: bind_1,
  277. unbind: unbind_1
  278. };
  279. /**
  280. * Module dependencies.
  281. */
  282. /**
  283. * Delegate event `type` to `selector`
  284. * and invoke `fn(e)`. A callback function
  285. * is returned which may be passed to `.unbind()`.
  286. *
  287. * @param {Element} el
  288. * @param {String} selector
  289. * @param {String} type
  290. * @param {Function} fn
  291. * @param {Boolean} capture
  292. * @return {Function}
  293. * @api public
  294. */
  295. // Some events don't bubble, so we want to bind to the capture phase instead
  296. // when delegating.
  297. var forceCaptureEvents = ['focus', 'blur'];
  298. function bind$1(el, selector, type, fn, capture) {
  299. if (forceCaptureEvents.indexOf(type) !== -1) {
  300. capture = true;
  301. }
  302. return componentEvent.bind(el, type, function (e) {
  303. var target = e.target || e.srcElement;
  304. e.delegateTarget = closest(target, selector, true, el);
  305. if (e.delegateTarget) {
  306. fn.call(el, e);
  307. }
  308. }, capture);
  309. }
  310. /**
  311. * Unbind event `type`'s callback `fn`.
  312. *
  313. * @param {Element} el
  314. * @param {String} type
  315. * @param {Function} fn
  316. * @param {Boolean} capture
  317. * @api public
  318. */
  319. function unbind$1(el, type, fn, capture) {
  320. if (forceCaptureEvents.indexOf(type) !== -1) {
  321. capture = true;
  322. }
  323. return componentEvent.unbind(el, type, fn, capture);
  324. }
  325. var delegate = {
  326. bind: bind$1,
  327. unbind: unbind$1
  328. };
  329. /**
  330. * Expose `parse`.
  331. */
  332. var domify = parse;
  333. /**
  334. * Tests for browser support.
  335. */
  336. var innerHTMLBug = false;
  337. var bugTestDiv;
  338. if (typeof document !== 'undefined') {
  339. bugTestDiv = document.createElement('div');
  340. // Setup
  341. bugTestDiv.innerHTML = ' <link/><table></table><a href="/a">a</a><input type="checkbox"/>';
  342. // Make sure that link elements get serialized correctly by innerHTML
  343. // This requires a wrapper element in IE
  344. innerHTMLBug = !bugTestDiv.getElementsByTagName('link').length;
  345. bugTestDiv = undefined;
  346. }
  347. /**
  348. * Wrap map from jquery.
  349. */
  350. var map = {
  351. legend: [1, '<fieldset>', '</fieldset>'],
  352. tr: [2, '<table><tbody>', '</tbody></table>'],
  353. col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
  354. // for script/link/style tags to work in IE6-8, you have to wrap
  355. // in a div with a non-whitespace character in front, ha!
  356. _default: innerHTMLBug ? [1, 'X<div>', '</div>'] : [0, '', '']
  357. };
  358. map.td =
  359. map.th = [3, '<table><tbody><tr>', '</tr></tbody></table>'];
  360. map.option =
  361. map.optgroup = [1, '<select multiple="multiple">', '</select>'];
  362. map.thead =
  363. map.tbody =
  364. map.colgroup =
  365. map.caption =
  366. map.tfoot = [1, '<table>', '</table>'];
  367. map.polyline =
  368. map.ellipse =
  369. map.polygon =
  370. map.circle =
  371. map.text =
  372. map.line =
  373. map.path =
  374. map.rect =
  375. map.g = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'];
  376. /**
  377. * Parse `html` and return a DOM Node instance, which could be a TextNode,
  378. * HTML DOM Node of some kind (<div> for example), or a DocumentFragment
  379. * instance, depending on the contents of the `html` string.
  380. *
  381. * @param {String} html - HTML string to "domify"
  382. * @param {Document} doc - The `document` instance to create the Node for
  383. * @return {DOMNode} the TextNode, DOM Node, or DocumentFragment instance
  384. * @api private
  385. */
  386. function parse(html, doc) {
  387. if ('string' != typeof html) throw new TypeError('String expected');
  388. // default to the global `document` object
  389. if (!doc) doc = document;
  390. // tag name
  391. var m = /<([\w:]+)/.exec(html);
  392. if (!m) return doc.createTextNode(html);
  393. html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace
  394. var tag = m[1];
  395. // body support
  396. if (tag == 'body') {
  397. var el = doc.createElement('html');
  398. el.innerHTML = html;
  399. return el.removeChild(el.lastChild);
  400. }
  401. // wrap map
  402. var wrap = map[tag] || map._default;
  403. var depth = wrap[0];
  404. var prefix = wrap[1];
  405. var suffix = wrap[2];
  406. var el = doc.createElement('div');
  407. el.innerHTML = prefix + html + suffix;
  408. while (depth--) el = el.lastChild;
  409. // one element
  410. if (el.firstChild == el.lastChild) {
  411. return el.removeChild(el.firstChild);
  412. }
  413. // several elements
  414. var fragment = doc.createDocumentFragment();
  415. while (el.firstChild) {
  416. fragment.appendChild(el.removeChild(el.firstChild));
  417. }
  418. return fragment;
  419. }
  420. function query(selector, el) {
  421. el = el || document;
  422. return el.querySelector(selector);
  423. }
  424. function all(selector, el) {
  425. el = el || document;
  426. return el.querySelectorAll(selector);
  427. }
  428. function remove(el) {
  429. el.parentNode && el.parentNode.removeChild(el);
  430. }
  431. exports.attr = attr;
  432. exports.classes = classes;
  433. exports.clear = clear;
  434. exports.closest = closest;
  435. exports.delegate = delegate;
  436. exports.domify = domify;
  437. exports.event = componentEvent;
  438. exports.matches = matchesSelector;
  439. exports.query = query;
  440. exports.queryAll = all;
  441. exports.remove = remove;