UNPKG

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