ClipboardJS.js 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109
  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. } else if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
  604. var isReadOnly = element.hasAttribute('readonly');
  605. if (!isReadOnly) {
  606. element.setAttribute('readonly', '');
  607. }
  608. element.select();
  609. element.setSelectionRange(0, element.value.length);
  610. if (!isReadOnly) {
  611. element.removeAttribute('readonly');
  612. }
  613. selectedText = element.value;
  614. } else {
  615. if (element.hasAttribute('contenteditable')) {
  616. element.focus();
  617. }
  618. var selection = window.getSelection();
  619. var range = document.createRange();
  620. range.selectNodeContents(element);
  621. selection.removeAllRanges();
  622. selection.addRange(range);
  623. selectedText = selection.toString();
  624. }
  625. return selectedText;
  626. }
  627. module.exports = select;
  628. /***/
  629. }),
  630. /* 3 */
  631. /***/ (function (module, exports) {
  632. function E() {
  633. // Keep this empty so it's easier to inherit from
  634. // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
  635. }
  636. E.prototype = {
  637. on: function (name, callback, ctx) {
  638. var e = this.e || (this.e = {});
  639. (e[name] || (e[name] = [])).push({
  640. fn: callback,
  641. ctx: ctx
  642. });
  643. return this;
  644. },
  645. once: function (name, callback, ctx) {
  646. var self = this;
  647. function listener() {
  648. self.off(name, listener);
  649. callback.apply(ctx, arguments);
  650. };
  651. listener._ = callback
  652. return this.on(name, listener, ctx);
  653. },
  654. emit: function (name) {
  655. var data = [].slice.call(arguments, 1);
  656. var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
  657. var i = 0;
  658. var len = evtArr.length;
  659. for (i; i < len; i++) {
  660. evtArr[i].fn.apply(evtArr[i].ctx, data);
  661. }
  662. return this;
  663. },
  664. off: function (name, callback) {
  665. var e = this.e || (this.e = {});
  666. var evts = e[name];
  667. var liveEvents = [];
  668. if (evts && callback) {
  669. for (var i = 0, len = evts.length; i < len; i++) {
  670. if (evts[i].fn !== callback && evts[i].fn._ !== callback)
  671. liveEvents.push(evts[i]);
  672. }
  673. }
  674. // Remove event from queue to prevent memory leak
  675. // Suggested by https://github.com/lazd
  676. // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
  677. (liveEvents.length)
  678. ? e[name] = liveEvents
  679. : delete e[name];
  680. return this;
  681. }
  682. };
  683. module.exports = E;
  684. /***/
  685. }),
  686. /* 4 */
  687. /***/ (function (module, exports, __webpack_require__) {
  688. var is = __webpack_require__(5);
  689. var delegate = __webpack_require__(6);
  690. /**
  691. * Validates all params and calls the right
  692. * listener function based on its target type.
  693. *
  694. * @param {String|HTMLElement|HTMLCollection|NodeList} target
  695. * @param {String} type
  696. * @param {Function} callback
  697. * @return {Object}
  698. */
  699. function listen(target, type, callback) {
  700. if (!target && !type && !callback) {
  701. throw new Error('Missing required arguments');
  702. }
  703. if (!is.string(type)) {
  704. throw new TypeError('Second argument must be a String');
  705. }
  706. if (!is.fn(callback)) {
  707. throw new TypeError('Third argument must be a Function');
  708. }
  709. if (is.node(target)) {
  710. return listenNode(target, type, callback);
  711. } else if (is.nodeList(target)) {
  712. return listenNodeList(target, type, callback);
  713. } else if (is.string(target)) {
  714. return listenSelector(target, type, callback);
  715. } else {
  716. throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');
  717. }
  718. }
  719. /**
  720. * Adds an event listener to a HTML element
  721. * and returns a remove listener function.
  722. *
  723. * @param {HTMLElement} node
  724. * @param {String} type
  725. * @param {Function} callback
  726. * @return {Object}
  727. */
  728. function listenNode(node, type, callback) {
  729. node.addEventListener(type, callback);
  730. return {
  731. destroy: function () {
  732. node.removeEventListener(type, callback);
  733. }
  734. }
  735. }
  736. /**
  737. * Add an event listener to a list of HTML elements
  738. * and returns a remove listener function.
  739. *
  740. * @param {NodeList|HTMLCollection} nodeList
  741. * @param {String} type
  742. * @param {Function} callback
  743. * @return {Object}
  744. */
  745. function listenNodeList(nodeList, type, callback) {
  746. Array.prototype.forEach.call(nodeList, function (node) {
  747. node.addEventListener(type, callback);
  748. });
  749. return {
  750. destroy: function () {
  751. Array.prototype.forEach.call(nodeList, function (node) {
  752. node.removeEventListener(type, callback);
  753. });
  754. }
  755. }
  756. }
  757. /**
  758. * Add an event listener to a selector
  759. * and returns a remove listener function.
  760. *
  761. * @param {String} selector
  762. * @param {String} type
  763. * @param {Function} callback
  764. * @return {Object}
  765. */
  766. function listenSelector(selector, type, callback) {
  767. return delegate(document.body, selector, type, callback);
  768. }
  769. module.exports = listen;
  770. /***/
  771. }),
  772. /* 5 */
  773. /***/ (function (module, exports) {
  774. /**
  775. * Check if argument is a HTML element.
  776. *
  777. * @param {Object} value
  778. * @return {Boolean}
  779. */
  780. exports.node = function (value) {
  781. return value !== undefined
  782. && value instanceof HTMLElement
  783. && value.nodeType === 1;
  784. };
  785. /**
  786. * Check if argument is a list of HTML elements.
  787. *
  788. * @param {Object} value
  789. * @return {Boolean}
  790. */
  791. exports.nodeList = function (value) {
  792. var type = Object.prototype.toString.call(value);
  793. return value !== undefined
  794. && (type === '[object NodeList]' || type === '[object HTMLCollection]')
  795. && ('length' in value)
  796. && (value.length === 0 || exports.node(value[0]));
  797. };
  798. /**
  799. * Check if argument is a string.
  800. *
  801. * @param {Object} value
  802. * @return {Boolean}
  803. */
  804. exports.string = function (value) {
  805. return typeof value === 'string'
  806. || value instanceof String;
  807. };
  808. /**
  809. * Check if argument is a function.
  810. *
  811. * @param {Object} value
  812. * @return {Boolean}
  813. */
  814. exports.fn = function (value) {
  815. var type = Object.prototype.toString.call(value);
  816. return type === '[object Function]';
  817. };
  818. /***/
  819. }),
  820. /* 6 */
  821. /***/ (function (module, exports, __webpack_require__) {
  822. var closest = __webpack_require__(7);
  823. /**
  824. * Delegates event to a selector.
  825. *
  826. * @param {Element} element
  827. * @param {String} selector
  828. * @param {String} type
  829. * @param {Function} callback
  830. * @param {Boolean} useCapture
  831. * @return {Object}
  832. */
  833. function _delegate(element, selector, type, callback, useCapture) {
  834. var listenerFn = listener.apply(this, arguments);
  835. element.addEventListener(type, listenerFn, useCapture);
  836. return {
  837. destroy: function () {
  838. element.removeEventListener(type, listenerFn, useCapture);
  839. }
  840. }
  841. }
  842. /**
  843. * Delegates event to a selector.
  844. *
  845. * @param {Element|String|Array} [elements]
  846. * @param {String} selector
  847. * @param {String} type
  848. * @param {Function} callback
  849. * @param {Boolean} useCapture
  850. * @return {Object}
  851. */
  852. function delegate(elements, selector, type, callback, useCapture) {
  853. // Handle the regular Element usage
  854. if (typeof elements.addEventListener === 'function') {
  855. return _delegate.apply(null, arguments);
  856. }
  857. // Handle Element-less usage, it defaults to global delegation
  858. if (typeof type === 'function') {
  859. // Use `document` as the first parameter, then apply arguments
  860. // This is a short way to .unshift `arguments` without running into deoptimizations
  861. return _delegate.bind(null, document).apply(null, arguments);
  862. }
  863. // Handle Selector-based usage
  864. if (typeof elements === 'string') {
  865. elements = document.querySelectorAll(elements);
  866. }
  867. // Handle Array-like based usage
  868. return Array.prototype.map.call(elements, function (element) {
  869. return _delegate(element, selector, type, callback, useCapture);
  870. });
  871. }
  872. /**
  873. * Finds closest match and invokes callback.
  874. *
  875. * @param {Element} element
  876. * @param {String} selector
  877. * @param {String} type
  878. * @param {Function} callback
  879. * @return {Function}
  880. */
  881. function listener(element, selector, type, callback) {
  882. return function (e) {
  883. e.delegateTarget = closest(e.target, selector);
  884. if (e.delegateTarget) {
  885. callback.call(element, e);
  886. }
  887. }
  888. }
  889. module.exports = delegate;
  890. /***/
  891. }),
  892. /* 7 */
  893. /***/ (function (module, exports) {
  894. var DOCUMENT_NODE_TYPE = 9;
  895. /**
  896. * A polyfill for Element.matches()
  897. */
  898. if (typeof Element !== 'undefined' && !Element.prototype.matches) {
  899. var proto = Element.prototype;
  900. proto.matches = proto.matchesSelector ||
  901. proto.mozMatchesSelector ||
  902. proto.msMatchesSelector ||
  903. proto.oMatchesSelector ||
  904. proto.webkitMatchesSelector;
  905. }
  906. /**
  907. * Finds the closest parent that matches a selector.
  908. *
  909. * @param {Element} element
  910. * @param {String} selector
  911. * @return {Function}
  912. */
  913. function closest(element, selector) {
  914. while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {
  915. if (typeof element.matches === 'function' &&
  916. element.matches(selector)) {
  917. return element;
  918. }
  919. element = element.parentNode;
  920. }
  921. }
  922. module.exports = closest;
  923. /***/
  924. })
  925. /******/]);
  926. });