ClipboardJS.js 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114
  1. /*!
  2. * clipboard.js v2.0.4
  3. * https://zenorocha.github.io/clipboard.js
  4. *
  5. * Licensed MIT © Zeno Rocha
  6. */
  7. (function webpackUniversalModuleDefinition(root, factory) {
  8. if (typeof exports === 'object' && typeof module === 'object') {
  9. module.exports = factory();
  10. } else if (typeof define === 'function' && define.amd) {
  11. define([], factory);
  12. } else if (typeof exports === 'object') {
  13. exports["ClipboardJS"] = factory();
  14. } else if (window.layui && layui.define) { // layui加载
  15. layui.define(function (exports) {
  16. exports('ClipboardJS', factory());
  17. });
  18. } else {
  19. root["ClipboardJS"] = factory();
  20. }
  21. })(this, function () {
  22. return /******/ (function (modules) { // webpackBootstrap
  23. /******/ // The module cache
  24. /******/
  25. var installedModules = {};
  26. /******/
  27. /******/ // The require function
  28. /******/
  29. function __webpack_require__(moduleId) {
  30. /******/
  31. /******/ // Check if module is in cache
  32. /******/
  33. if (installedModules[moduleId]) {
  34. /******/
  35. return installedModules[moduleId].exports;
  36. /******/
  37. }
  38. /******/ // Create a new module (and put it into the cache)
  39. /******/
  40. var module = installedModules[moduleId] = {
  41. /******/ i: moduleId,
  42. /******/ l: false,
  43. /******/ exports: {}
  44. /******/
  45. };
  46. /******/
  47. /******/ // Execute the module function
  48. /******/
  49. modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
  50. /******/
  51. /******/ // Flag the module as loaded
  52. /******/
  53. module.l = true;
  54. /******/
  55. /******/ // Return the exports of the module
  56. /******/
  57. return module.exports;
  58. /******/
  59. }
  60. /******/
  61. /******/
  62. /******/ // expose the modules object (__webpack_modules__)
  63. /******/
  64. __webpack_require__.m = modules;
  65. /******/
  66. /******/ // expose the module cache
  67. /******/
  68. __webpack_require__.c = installedModules;
  69. /******/
  70. /******/ // define getter function for harmony exports
  71. /******/
  72. __webpack_require__.d = function (exports, name, getter) {
  73. /******/
  74. if (!__webpack_require__.o(exports, name)) {
  75. /******/
  76. Object.defineProperty(exports, name, {enumerable: true, get: getter});
  77. /******/
  78. }
  79. /******/
  80. };
  81. /******/
  82. /******/ // define __esModule on exports
  83. /******/
  84. __webpack_require__.r = function (exports) {
  85. /******/
  86. if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
  87. /******/
  88. Object.defineProperty(exports, Symbol.toStringTag, {value: 'Module'});
  89. /******/
  90. }
  91. /******/
  92. Object.defineProperty(exports, '__esModule', {value: true});
  93. /******/
  94. };
  95. /******/
  96. /******/ // create a fake namespace object
  97. /******/ // mode & 1: value is a module id, require it
  98. /******/ // mode & 2: merge all properties of value into the ns
  99. /******/ // mode & 4: return value when already ns object
  100. /******/ // mode & 8|1: behave like require
  101. /******/
  102. __webpack_require__.t = function (value, mode) {
  103. /******/
  104. if (mode & 1) value = __webpack_require__(value);
  105. /******/
  106. if (mode & 8) return value;
  107. /******/
  108. if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
  109. /******/
  110. var ns = Object.create(null);
  111. /******/
  112. __webpack_require__.r(ns);
  113. /******/
  114. Object.defineProperty(ns, 'default', {enumerable: true, value: value});
  115. /******/
  116. if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) {
  117. return value[key];
  118. }.bind(null, key));
  119. /******/
  120. return ns;
  121. /******/
  122. };
  123. /******/
  124. /******/ // getDefaultExport function for compatibility with non-harmony modules
  125. /******/
  126. __webpack_require__.n = function (module) {
  127. /******/
  128. var getter = module && module.__esModule ?
  129. /******/ function getDefault() {
  130. return module['default'];
  131. } :
  132. /******/ function getModuleExports() {
  133. return module;
  134. };
  135. /******/
  136. __webpack_require__.d(getter, 'a', getter);
  137. /******/
  138. return getter;
  139. /******/
  140. };
  141. /******/
  142. /******/ // Object.prototype.hasOwnProperty.call
  143. /******/
  144. __webpack_require__.o = function (object, property) {
  145. return Object.prototype.hasOwnProperty.call(object, property);
  146. };
  147. /******/
  148. /******/ // __webpack_public_path__
  149. /******/
  150. __webpack_require__.p = "";
  151. /******/
  152. /******/
  153. /******/ // Load entry module and return exports
  154. /******/
  155. return __webpack_require__(__webpack_require__.s = 0);
  156. /******/
  157. })
  158. /************************************************************************/
  159. /******/([
  160. /* 0 */
  161. /***/ (function (module, exports, __webpack_require__) {
  162. "use strict";
  163. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  164. return typeof obj;
  165. } : function (obj) {
  166. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  167. };
  168. var _createClass = function () {
  169. function defineProperties(target, props) {
  170. for (var i = 0; i < props.length; i++) {
  171. var descriptor = props[i];
  172. descriptor.enumerable = descriptor.enumerable || false;
  173. descriptor.configurable = true;
  174. if ("value" in descriptor) descriptor.writable = true;
  175. Object.defineProperty(target, descriptor.key, descriptor);
  176. }
  177. }
  178. return function (Constructor, protoProps, staticProps) {
  179. if (protoProps) defineProperties(Constructor.prototype, protoProps);
  180. if (staticProps) defineProperties(Constructor, staticProps);
  181. return Constructor;
  182. };
  183. }();
  184. var _clipboardAction = __webpack_require__(1);
  185. var _clipboardAction2 = _interopRequireDefault(_clipboardAction);
  186. var _tinyEmitter = __webpack_require__(3);
  187. var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);
  188. var _goodListener = __webpack_require__(4);
  189. var _goodListener2 = _interopRequireDefault(_goodListener);
  190. function _interopRequireDefault(obj) {
  191. return obj && obj.__esModule ? obj : {default: obj};
  192. }
  193. function _classCallCheck(instance, Constructor) {
  194. if (!(instance instanceof Constructor)) {
  195. throw new TypeError("Cannot call a class as a function");
  196. }
  197. }
  198. function _possibleConstructorReturn(self, call) {
  199. if (!self) {
  200. throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  201. }
  202. return call && (typeof call === "object" || typeof call === "function") ? call : self;
  203. }
  204. function _inherits(subClass, superClass) {
  205. if (typeof superClass !== "function" && superClass !== null) {
  206. throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  207. }
  208. subClass.prototype = Object.create(superClass && superClass.prototype, {
  209. constructor: {
  210. value: subClass,
  211. enumerable: false,
  212. writable: true,
  213. configurable: true
  214. }
  215. });
  216. if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  217. }
  218. /**
  219. * Base class which takes one or more elements, adds event listeners to them,
  220. * and instantiates a new `ClipboardAction` on each click.
  221. */
  222. var Clipboard = function (_Emitter) {
  223. _inherits(Clipboard, _Emitter);
  224. /**
  225. * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
  226. * @param {Object} options
  227. */
  228. function Clipboard(trigger, options) {
  229. _classCallCheck(this, Clipboard);
  230. var _this = _possibleConstructorReturn(this, (Clipboard.__proto__ || Object.getPrototypeOf(Clipboard)).call(this));
  231. _this.resolveOptions(options);
  232. _this.listenClick(trigger);
  233. return _this;
  234. }
  235. /**
  236. * Defines if attributes would be resolved using internal setter functions
  237. * or custom functions that were passed in the constructor.
  238. * @param {Object} options
  239. */
  240. _createClass(Clipboard, [{
  241. key: 'resolveOptions',
  242. value: function resolveOptions() {
  243. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  244. this.action = typeof options.action === 'function' ? options.action : this.defaultAction;
  245. this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;
  246. this.text = typeof options.text === 'function' ? options.text : this.defaultText;
  247. this.container = _typeof(options.container) === 'object' ? options.container : document.body;
  248. }
  249. /**
  250. * Adds a click event listener to the passed trigger.
  251. * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
  252. */
  253. }, {
  254. key: 'listenClick',
  255. value: function listenClick(trigger) {
  256. var _this2 = this;
  257. this.listener = (0, _goodListener2.default)(trigger, 'click', function (e) {
  258. return _this2.onClick(e);
  259. });
  260. }
  261. /**
  262. * Defines a new `ClipboardAction` on each click event.
  263. * @param {Event} e
  264. */
  265. }, {
  266. key: 'onClick',
  267. value: function onClick(e) {
  268. var trigger = e.delegateTarget || e.currentTarget;
  269. if (this.clipboardAction) {
  270. this.clipboardAction = null;
  271. }
  272. this.clipboardAction = new _clipboardAction2.default({
  273. action: this.action(trigger),
  274. target: this.target(trigger),
  275. text: this.text(trigger),
  276. container: this.container,
  277. trigger: trigger,
  278. emitter: this
  279. });
  280. }
  281. /**
  282. * Default `action` lookup function.
  283. * @param {Element} trigger
  284. */
  285. }, {
  286. key: 'defaultAction',
  287. value: function defaultAction(trigger) {
  288. return getAttributeValue('action', trigger);
  289. }
  290. /**
  291. * Default `target` lookup function.
  292. * @param {Element} trigger
  293. */
  294. }, {
  295. key: 'defaultTarget',
  296. value: function defaultTarget(trigger) {
  297. var selector = getAttributeValue('target', trigger);
  298. if (selector) {
  299. return document.querySelector(selector);
  300. }
  301. }
  302. /**
  303. * Returns the support of the given action, or all actions if no action is
  304. * given.
  305. * @param {String} [action]
  306. */
  307. }, {
  308. key: 'defaultText',
  309. /**
  310. * Default `text` lookup function.
  311. * @param {Element} trigger
  312. */
  313. value: function defaultText(trigger) {
  314. return getAttributeValue('text', trigger);
  315. }
  316. /**
  317. * Destroy lifecycle.
  318. */
  319. }, {
  320. key: 'destroy',
  321. value: function destroy() {
  322. this.listener.destroy();
  323. if (this.clipboardAction) {
  324. this.clipboardAction.destroy();
  325. this.clipboardAction = null;
  326. }
  327. }
  328. }], [{
  329. key: 'isSupported',
  330. value: function isSupported() {
  331. var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['copy', 'cut'];
  332. var actions = typeof action === 'string' ? [action] : action;
  333. var support = !!document.queryCommandSupported;
  334. actions.forEach(function (action) {
  335. support = support && !!document.queryCommandSupported(action);
  336. });
  337. return support;
  338. }
  339. }]);
  340. return Clipboard;
  341. }(_tinyEmitter2.default);
  342. /**
  343. * Helper function to retrieve attribute value.
  344. * @param {String} suffix
  345. * @param {Element} element
  346. */
  347. function getAttributeValue(suffix, element) {
  348. var attribute = 'data-clipboard-' + suffix;
  349. if (!element.hasAttribute(attribute)) {
  350. return;
  351. }
  352. return element.getAttribute(attribute);
  353. }
  354. module.exports = Clipboard;
  355. /***/
  356. }),
  357. /* 1 */
  358. /***/ (function (module, exports, __webpack_require__) {
  359. "use strict";
  360. var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
  361. return typeof obj;
  362. } : function (obj) {
  363. return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
  364. };
  365. var _createClass = function () {
  366. function defineProperties(target, props) {
  367. for (var i = 0; i < props.length; i++) {
  368. var descriptor = props[i];
  369. descriptor.enumerable = descriptor.enumerable || false;
  370. descriptor.configurable = true;
  371. if ("value" in descriptor) descriptor.writable = true;
  372. Object.defineProperty(target, descriptor.key, descriptor);
  373. }
  374. }
  375. return function (Constructor, protoProps, staticProps) {
  376. if (protoProps) defineProperties(Constructor.prototype, protoProps);
  377. if (staticProps) defineProperties(Constructor, staticProps);
  378. return Constructor;
  379. };
  380. }();
  381. var _select = __webpack_require__(2);
  382. var _select2 = _interopRequireDefault(_select);
  383. function _interopRequireDefault(obj) {
  384. return obj && obj.__esModule ? obj : {default: obj};
  385. }
  386. function _classCallCheck(instance, Constructor) {
  387. if (!(instance instanceof Constructor)) {
  388. throw new TypeError("Cannot call a class as a function");
  389. }
  390. }
  391. /**
  392. * Inner class which performs selection from either `text` or `target`
  393. * properties and then executes copy or cut operations.
  394. */
  395. var ClipboardAction = function () {
  396. /**
  397. * @param {Object} options
  398. */
  399. function ClipboardAction(options) {
  400. _classCallCheck(this, ClipboardAction);
  401. this.resolveOptions(options);
  402. this.initSelection();
  403. }
  404. /**
  405. * Defines base properties passed from constructor.
  406. * @param {Object} options
  407. */
  408. _createClass(ClipboardAction, [{
  409. key: 'resolveOptions',
  410. value: function resolveOptions() {
  411. var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  412. this.action = options.action;
  413. this.container = options.container;
  414. this.emitter = options.emitter;
  415. this.target = options.target;
  416. this.text = options.text;
  417. this.trigger = options.trigger;
  418. this.selectedText = '';
  419. }
  420. /**
  421. * Decides which selection strategy is going to be applied based
  422. * on the existence of `text` and `target` properties.
  423. */
  424. }, {
  425. key: 'initSelection',
  426. value: function initSelection() {
  427. if (this.text) {
  428. this.selectFake();
  429. } else if (this.target) {
  430. this.selectTarget();
  431. }
  432. }
  433. /**
  434. * Creates a fake textarea element, sets its value from `text` property,
  435. * and makes a selection on it.
  436. */
  437. }, {
  438. key: 'selectFake',
  439. value: function selectFake() {
  440. var _this = this;
  441. var isRTL = document.documentElement.getAttribute('dir') == 'rtl';
  442. this.removeFake();
  443. this.fakeHandlerCallback = function () {
  444. return _this.removeFake();
  445. };
  446. this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true;
  447. this.fakeElem = document.createElement('textarea');
  448. // Prevent zooming on iOS
  449. this.fakeElem.style.fontSize = '12pt';
  450. // Reset box model
  451. this.fakeElem.style.border = '0';
  452. this.fakeElem.style.padding = '0';
  453. this.fakeElem.style.margin = '0';
  454. // Move element out of screen horizontally
  455. this.fakeElem.style.position = 'absolute';
  456. this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';
  457. // Move element to the same position vertically
  458. var yPosition = window.pageYOffset || document.documentElement.scrollTop;
  459. this.fakeElem.style.top = yPosition + 'px';
  460. this.fakeElem.setAttribute('readonly', '');
  461. this.fakeElem.value = this.text;
  462. this.container.appendChild(this.fakeElem);
  463. this.selectedText = (0, _select2.default)(this.fakeElem);
  464. this.copyText();
  465. }
  466. /**
  467. * Only removes the fake element after another click event, that way
  468. * a user can hit `Ctrl+C` to copy because selection still exists.
  469. */
  470. }, {
  471. key: 'removeFake',
  472. value: function removeFake() {
  473. if (this.fakeHandler) {
  474. this.container.removeEventListener('click', this.fakeHandlerCallback);
  475. this.fakeHandler = null;
  476. this.fakeHandlerCallback = null;
  477. }
  478. if (this.fakeElem) {
  479. this.container.removeChild(this.fakeElem);
  480. this.fakeElem = null;
  481. }
  482. }
  483. /**
  484. * Selects the content from element passed on `target` property.
  485. */
  486. }, {
  487. key: 'selectTarget',
  488. value: function selectTarget() {
  489. this.selectedText = (0, _select2.default)(this.target);
  490. this.copyText();
  491. }
  492. /**
  493. * Executes the copy operation based on the current selection.
  494. */
  495. }, {
  496. key: 'copyText',
  497. value: function copyText() {
  498. var succeeded = void 0;
  499. try {
  500. succeeded = document.execCommand(this.action);
  501. } catch (err) {
  502. succeeded = false;
  503. }
  504. this.handleResult(succeeded);
  505. }
  506. /**
  507. * Fires an event based on the copy operation result.
  508. * @param {Boolean} succeeded
  509. */
  510. }, {
  511. key: 'handleResult',
  512. value: function handleResult(succeeded) {
  513. this.emitter.emit(succeeded ? 'success' : 'error', {
  514. action: this.action,
  515. text: this.selectedText,
  516. trigger: this.trigger,
  517. clearSelection: this.clearSelection.bind(this)
  518. });
  519. }
  520. /**
  521. * Moves focus away from `target` and back to the trigger, removes current selection.
  522. */
  523. }, {
  524. key: 'clearSelection',
  525. value: function clearSelection() {
  526. if (this.trigger) {
  527. this.trigger.focus();
  528. }
  529. window.getSelection().removeAllRanges();
  530. }
  531. /**
  532. * Sets the `action` to be performed which can be either 'copy' or 'cut'.
  533. * @param {String} action
  534. */
  535. }, {
  536. key: 'destroy',
  537. /**
  538. * Destroy lifecycle.
  539. */
  540. value: function destroy() {
  541. this.removeFake();
  542. }
  543. }, {
  544. key: 'action',
  545. set: function set() {
  546. var action = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'copy';
  547. this._action = action;
  548. if (this._action !== 'copy' && this._action !== 'cut') {
  549. throw new Error('Invalid "action" value, use either "copy" or "cut"');
  550. }
  551. }
  552. /**
  553. * Gets the `action` property.
  554. * @return {String}
  555. */
  556. ,
  557. get: function get() {
  558. return this._action;
  559. }
  560. /**
  561. * Sets the `target` property using an element
  562. * that will be have its content copied.
  563. * @param {Element} target
  564. */
  565. }, {
  566. key: 'target',
  567. set: function set(target) {
  568. if (target !== undefined) {
  569. if (target && (typeof target === 'undefined' ? 'undefined' : _typeof(target)) === 'object' && target.nodeType === 1) {
  570. if (this.action === 'copy' && target.hasAttribute('disabled')) {
  571. throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');
  572. }
  573. if (this.action === 'cut' && (target.hasAttribute('readonly') || target.hasAttribute('disabled'))) {
  574. throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');
  575. }
  576. this._target = target;
  577. } else {
  578. throw new Error('Invalid "target" value, use a valid Element');
  579. }
  580. }
  581. }
  582. /**
  583. * Gets the `target` property.
  584. * @return {String|HTMLElement}
  585. */
  586. ,
  587. get: function get() {
  588. return this._target;
  589. }
  590. }]);
  591. return ClipboardAction;
  592. }();
  593. module.exports = ClipboardAction;
  594. /***/
  595. }),
  596. /* 2 */
  597. /***/ (function (module, exports) {
  598. function select(element) {
  599. var selectedText;
  600. if (element.nodeName === 'SELECT') {
  601. element.focus();
  602. selectedText = element.value;
  603. }
  604. else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
  605. var isReadOnly = element.hasAttribute('readonly');
  606. if (!isReadOnly) {
  607. element.setAttribute('readonly', '');
  608. }
  609. element.select();
  610. element.setSelectionRange(0, element.value.length);
  611. if (!isReadOnly) {
  612. element.removeAttribute('readonly');
  613. }
  614. selectedText = element.value;
  615. }
  616. else {
  617. if (element.hasAttribute('contenteditable')) {
  618. element.focus();
  619. }
  620. var selection = window.getSelection();
  621. var range = document.createRange();
  622. range.selectNodeContents(element);
  623. selection.removeAllRanges();
  624. selection.addRange(range);
  625. selectedText = selection.toString();
  626. }
  627. return selectedText;
  628. }
  629. module.exports = select;
  630. /***/
  631. }),
  632. /* 3 */
  633. /***/ (function (module, exports) {
  634. function E() {
  635. // Keep this empty so it's easier to inherit from
  636. // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
  637. }
  638. E.prototype = {
  639. on: function (name, callback, ctx) {
  640. var e = this.e || (this.e = {});
  641. (e[name] || (e[name] = [])).push({
  642. fn: callback,
  643. ctx: ctx
  644. });
  645. return this;
  646. },
  647. once: function (name, callback, ctx) {
  648. var self = this;
  649. function listener() {
  650. self.off(name, listener);
  651. callback.apply(ctx, arguments);
  652. };
  653. listener._ = callback
  654. return this.on(name, listener, ctx);
  655. },
  656. emit: function (name) {
  657. var data = [].slice.call(arguments, 1);
  658. var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
  659. var i = 0;
  660. var len = evtArr.length;
  661. for (i; i < len; i++) {
  662. evtArr[i].fn.apply(evtArr[i].ctx, data);
  663. }
  664. return this;
  665. },
  666. off: function (name, callback) {
  667. var e = this.e || (this.e = {});
  668. var evts = e[name];
  669. var liveEvents = [];
  670. if (evts && callback) {
  671. for (var i = 0, len = evts.length; i < len; i++) {
  672. if (evts[i].fn !== callback && evts[i].fn._ !== callback)
  673. liveEvents.push(evts[i]);
  674. }
  675. }
  676. // Remove event from queue to prevent memory leak
  677. // Suggested by https://github.com/lazd
  678. // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
  679. (liveEvents.length)
  680. ? e[name] = liveEvents
  681. : delete e[name];
  682. return this;
  683. }
  684. };
  685. module.exports = E;
  686. /***/
  687. }),
  688. /* 4 */
  689. /***/ (function (module, exports, __webpack_require__) {
  690. var is = __webpack_require__(5);
  691. var delegate = __webpack_require__(6);
  692. /**
  693. * Validates all params and calls the right
  694. * listener function based on its target type.
  695. *
  696. * @param {String|HTMLElement|HTMLCollection|NodeList} target
  697. * @param {String} type
  698. * @param {Function} callback
  699. * @return {Object}
  700. */
  701. function listen(target, type, callback) {
  702. if (!target && !type && !callback) {
  703. throw new Error('Missing required arguments');
  704. }
  705. if (!is.string(type)) {
  706. throw new TypeError('Second argument must be a String');
  707. }
  708. if (!is.fn(callback)) {
  709. throw new TypeError('Third argument must be a Function');
  710. }
  711. if (is.node(target)) {
  712. return listenNode(target, type, callback);
  713. }
  714. else if (is.nodeList(target)) {
  715. return listenNodeList(target, type, callback);
  716. }
  717. else if (is.string(target)) {
  718. return listenSelector(target, type, callback);
  719. }
  720. else {
  721. throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');
  722. }
  723. }
  724. /**
  725. * Adds an event listener to a HTML element
  726. * and returns a remove listener function.
  727. *
  728. * @param {HTMLElement} node
  729. * @param {String} type
  730. * @param {Function} callback
  731. * @return {Object}
  732. */
  733. function listenNode(node, type, callback) {
  734. node.addEventListener(type, callback);
  735. return {
  736. destroy: function () {
  737. node.removeEventListener(type, callback);
  738. }
  739. }
  740. }
  741. /**
  742. * Add an event listener to a list of HTML elements
  743. * and returns a remove listener function.
  744. *
  745. * @param {NodeList|HTMLCollection} nodeList
  746. * @param {String} type
  747. * @param {Function} callback
  748. * @return {Object}
  749. */
  750. function listenNodeList(nodeList, type, callback) {
  751. Array.prototype.forEach.call(nodeList, function (node) {
  752. node.addEventListener(type, callback);
  753. });
  754. return {
  755. destroy: function () {
  756. Array.prototype.forEach.call(nodeList, function (node) {
  757. node.removeEventListener(type, callback);
  758. });
  759. }
  760. }
  761. }
  762. /**
  763. * Add an event listener to a selector
  764. * and returns a remove listener function.
  765. *
  766. * @param {String} selector
  767. * @param {String} type
  768. * @param {Function} callback
  769. * @return {Object}
  770. */
  771. function listenSelector(selector, type, callback) {
  772. return delegate(document.body, selector, type, callback);
  773. }
  774. module.exports = listen;
  775. /***/
  776. }),
  777. /* 5 */
  778. /***/ (function (module, exports) {
  779. /**
  780. * Check if argument is a HTML element.
  781. *
  782. * @param {Object} value
  783. * @return {Boolean}
  784. */
  785. exports.node = function (value) {
  786. return value !== undefined
  787. && value instanceof HTMLElement
  788. && value.nodeType === 1;
  789. };
  790. /**
  791. * Check if argument is a list of HTML elements.
  792. *
  793. * @param {Object} value
  794. * @return {Boolean}
  795. */
  796. exports.nodeList = function (value) {
  797. var type = Object.prototype.toString.call(value);
  798. return value !== undefined
  799. && (type === '[object NodeList]' || type === '[object HTMLCollection]')
  800. && ('length' in value)
  801. && (value.length === 0 || exports.node(value[0]));
  802. };
  803. /**
  804. * Check if argument is a string.
  805. *
  806. * @param {Object} value
  807. * @return {Boolean}
  808. */
  809. exports.string = function (value) {
  810. return typeof value === 'string'
  811. || value instanceof String;
  812. };
  813. /**
  814. * Check if argument is a function.
  815. *
  816. * @param {Object} value
  817. * @return {Boolean}
  818. */
  819. exports.fn = function (value) {
  820. var type = Object.prototype.toString.call(value);
  821. return type === '[object Function]';
  822. };
  823. /***/
  824. }),
  825. /* 6 */
  826. /***/ (function (module, exports, __webpack_require__) {
  827. var closest = __webpack_require__(7);
  828. /**
  829. * Delegates event to a selector.
  830. *
  831. * @param {Element} element
  832. * @param {String} selector
  833. * @param {String} type
  834. * @param {Function} callback
  835. * @param {Boolean} useCapture
  836. * @return {Object}
  837. */
  838. function _delegate(element, selector, type, callback, useCapture) {
  839. var listenerFn = listener.apply(this, arguments);
  840. element.addEventListener(type, listenerFn, useCapture);
  841. return {
  842. destroy: function () {
  843. element.removeEventListener(type, listenerFn, useCapture);
  844. }
  845. }
  846. }
  847. /**
  848. * Delegates event to a selector.
  849. *
  850. * @param {Element|String|Array} [elements]
  851. * @param {String} selector
  852. * @param {String} type
  853. * @param {Function} callback
  854. * @param {Boolean} useCapture
  855. * @return {Object}
  856. */
  857. function delegate(elements, selector, type, callback, useCapture) {
  858. // Handle the regular Element usage
  859. if (typeof elements.addEventListener === 'function') {
  860. return _delegate.apply(null, arguments);
  861. }
  862. // Handle Element-less usage, it defaults to global delegation
  863. if (typeof type === 'function') {
  864. // Use `document` as the first parameter, then apply arguments
  865. // This is a short way to .unshift `arguments` without running into deoptimizations
  866. return _delegate.bind(null, document).apply(null, arguments);
  867. }
  868. // Handle Selector-based usage
  869. if (typeof elements === 'string') {
  870. elements = document.querySelectorAll(elements);
  871. }
  872. // Handle Array-like based usage
  873. return Array.prototype.map.call(elements, function (element) {
  874. return _delegate(element, selector, type, callback, useCapture);
  875. });
  876. }
  877. /**
  878. * Finds closest match and invokes callback.
  879. *
  880. * @param {Element} element
  881. * @param {String} selector
  882. * @param {String} type
  883. * @param {Function} callback
  884. * @return {Function}
  885. */
  886. function listener(element, selector, type, callback) {
  887. return function (e) {
  888. e.delegateTarget = closest(e.target, selector);
  889. if (e.delegateTarget) {
  890. callback.call(element, e);
  891. }
  892. }
  893. }
  894. module.exports = delegate;
  895. /***/
  896. }),
  897. /* 7 */
  898. /***/ (function (module, exports) {
  899. var DOCUMENT_NODE_TYPE = 9;
  900. /**
  901. * A polyfill for Element.matches()
  902. */
  903. if (typeof Element !== 'undefined' && !Element.prototype.matches) {
  904. var proto = Element.prototype;
  905. proto.matches = proto.matchesSelector ||
  906. proto.mozMatchesSelector ||
  907. proto.msMatchesSelector ||
  908. proto.oMatchesSelector ||
  909. proto.webkitMatchesSelector;
  910. }
  911. /**
  912. * Finds the closest parent that matches a selector.
  913. *
  914. * @param {Element} element
  915. * @param {String} selector
  916. * @return {Function}
  917. */
  918. function closest(element, selector) {
  919. while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {
  920. if (typeof element.matches === 'function' &&
  921. element.matches(selector)) {
  922. return element;
  923. }
  924. element = element.parentNode;
  925. }
  926. }
  927. module.exports = closest;
  928. /***/
  929. })
  930. /******/]);
  931. });