PageSourceSearch

https://witmem.com/js/clipboard.js

js witmem.com collected 2026-10-08 08:21:35 UTC 20,963 bytes, 745 lines download raw bytes

1/*!
2 * clipboard.js v1.5.5
3 * https://zenorocha.github.io/clipboard.js
4 *
5 * Licensed MIT © Zeno Rocha
6 */
7(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Clipboard = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
8var matches = require('matches-selector')
9
10module.exports = function (element, selector, checkYoSelf) {
11  var parent = checkYoSelf ? element : element.parentNode
12
13  while (parent && parent !== document) {
14    if (matches(parent, selector)) return parent;
15    parent = parent.parentNode
16  }
17}
18
19},{"matches-selector":2}],2:[function(require,module,exports){
20
21/**
22 * Element prototype.
23 */
24
25var proto = Element.prototype;
26
27/**
28 * Vendor function.
29 */
30
31var vendor = proto.matchesSelector
32  || proto.webkitMatchesSelector
33  || proto.mozMatchesSelector
34  || proto.msMatchesSelector
35  || proto.oMatchesSelector;
36
37/**
38 * Expose `match()`.
39 */
40
41module.exports = match;
42
43/**
44 * Match `el` to `selector`.
45 *
46 * @param {Element} el
47 * @param {String} selector
48 * @return {Boolean}
49 * @api public
50 */
51
52function match(el, selector) {
53  if (vendor) return vendor.call(el, selector);
54  var nodes = el.parentNode.querySelectorAll(selector);
55  for (var i = 0; i < nodes.length; ++i) {
56    if (nodes[i] == el) return true;
57  }
58  return false;
59}
60},{}],3:[function(require,module,exports){
61var closest = require('closest');
62
63/**
64 * Delegates event to a selector.
65 *
66 * @param {Element} element
67 * @param {String} selector
68 * @param {String} type
69 * @param {Function} callback
70 * @return {Object}
71 */
72function delegate(element, selector, type, callback) {
73    var listenerFn = listener.apply(this, arguments);
74
75    element.addEventListener(type, listenerFn);
76
77    return {
78        destroy: function() {
79            element.removeEventListener(type, listenerFn);
80        }
81    }
82}
83
84/**
85 * Finds closest match and invokes callback.
86 *
87 * @param {Element} element
88 * @param {String} selector
89 * @param {String} type
90 * @param {Function} callback
91 * @return {Function}
92 */
93function listener(element, selector, type, callback) {
94    return function(e) {
95        e.delegateTarget = closest(e.target, selector, true);
96
97        if (e.delegateTarget) {
98            callback.call(element, e);
99        }
100    }
101}
102
103module.exports = delegate;
104
105},{"closest":1}],4:[function(require,module,exports){
106/**
107 * Check if argument is a HTML element.
108 *
109 * @param {Object} value
110 * @return {Boolean}
111 */
112exports.node = function(value) {
113    return value !== undefined
114        && value instanceof HTMLElement
115        && value.nodeType === 1;
116};
117
118/**
119 * Check if argument is a list of HTML elements.
120 *
121 * @param {Object} value
122 * @return {Boolean}
123 */
124exports.nodeList = function(value) {
125    var type = Object.prototype.toString.call(value);
126
127    return value !== undefined
128        && (type === '[object NodeList]' || type === '[object HTMLCollection]')
129        && ('length' in value)
130        && (value.length === 0 || exports.node(value[0]));
131};
132
133/**
134 * Check if argument is a string.
135 *
136 * @param {Object} value
137 * @return {Boolean}
138 */
139exports.string = function(value) {
140    return typeof value === 'string'
141        || value instanceof String;
142};
143
144/**
145 * Check if argument is a function.
146 *
147 * @param {Object} value
148 * @return {Boolean}
149 */
150exports.function = function(value) {
151    var type = Object.prototype.toString.call(value);
152
153    return type === '[object Function]';
154};
155
156},{}],5:[function(require,module,exports){
157var is = require('./is');
158var delegate = require('delegate');
159
160/**
161 * Validates all params and calls the right
162 * listener function based on its target type.
163 *
164 * @param {String|HTMLElement|HTMLCollection|NodeList} target
165 * @param {String} type
166 * @param {Function} callback
167 * @return {Object}
168 */
169function listen(target, type, callback) {
170    if (!target && !type && !callback) {
171        throw new Error('Missing required arguments');
172    }
173
174    if (!is.string(type)) {
175        throw new TypeError('Second argument must be a String');
176    }
177
178    if (!is.function(callback)) {
179        throw new TypeError('Third argument must be a Function');
180    }
181
182    if (is.node(target)) {
183        return listenNode(target, type, callback);
184    }
185    else if (is.nodeList(target)) {
186        return listenNodeList(target, type, callback);
187    }
188    else if (is.string(target)) {
189        return listenSelector(target, type, callback);
190    }
191    else {
192        throw new TypeError('First argument must be a String, HTMLElement, HTMLCollection, or NodeList');
193    }
194}
195
196/**
197 * Adds an event listener to a HTML element
198 * and returns a remove listener function.
199 *
200 * @param {HTMLElement} node
201 * @param {String} type
202 * @param {Function} callback
203 * @return {Object}
204 */
205function listenNode(node, type, callback) {
206    node.addEventListener(type, callback);
207
208    return {
209        destroy: function() {
210            node.removeEventListener(type, callback);
211        }
212    }
213}
214
215/**
216 * Add an event listener to a list of HTML elements
217 * and returns a remove listener function.
218 *
219 * @param {NodeList|HTMLCollection} nodeList
220 * @param {String} type
221 * @param {Function} callback
222 * @return {Object}
223 */
224function listenNodeList(nodeList, type, callback) {
225    Array.prototype.forEach.call(nodeList, function(node) {
226        node.addEventListener(type, callback);
227    });
228
229    return {
230        destroy: function() {
231            Array.prototype.forEach.call(nodeList, function(node) {
232                node.removeEventListener(type, callback);
233            });
234        }
235    }
236}
237
238/**
239 * Add an event listener to a selector
240 * and returns a remove listener function.
241 *
242 * @param {String} selector
243 * @param {String} type
244 * @param {Function} callback
245 * @return {Object}
246 */
247function listenSelector(selector, type, callback) {
248    return delegate(document.body, selector, type, callback);
249}
250
251module.exports = listen;
252
253},{"./is":4,"delegate":3}],6:[function(require,module,exports){
254function select(element) {
255    var selectedText;
256
257    if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
258        element.focus();
259        element.setSelectionRange(0, element.value.length);
260
261        selectedText = element.value;
262    }
263    else {
264        if (element.hasAttribute('contenteditable')) {
265            element.focus();
266        }
267
268        var selection = window.getSelection();
269        var range = document.createRange();
270
271        range.selectNodeContents(element);
272        selection.removeAllRanges();
273        selection.addRange(range);
274
275        selectedText = selection.toString();
276    }
277
278    return selectedText;
279}
280
281module.exports = select;
282
283},{}],7:[function(require,module,exports){
284function E () {
285	// Keep this empty so it's easier to inherit from
286  // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
287}
288
289E.prototype = {
290	on: function (name, callback, ctx) {
291    var e = this.e || (this.e = {});
292
293    (e[name] || (e[name] = [])).push({
294      fn: callback,
295      ctx: ctx
296    });
297
298    return this;
299  },
300
301  once: function (name, callback, ctx) {
302    var self = this;
303    function listener () {
304      self.off(name, listener);
305      callback.apply(ctx, arguments);
306    };
307
308    listener._ = callback
309    return this.on(name, listener, ctx);
310  },
311
312  emit: function (name) {
313    var data = [].slice.call(arguments, 1);
314    var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
315    var i = 0;
316    var len = evtArr.length;
317
318    for (i; i < len; i++) {
319      evtArr[i].fn.apply(evtArr[i].ctx, data);
320    }
321
322    return this;
323  },
324
325  off: function (name, callback) {
326    var e = this.e || (this.e = {});
327    var evts = e[name];
328    var liveEvents = [];
329
330    if (evts && callback) {
331      for (var i = 0, len = evts.length; i < len; i++) {
332        if (evts[i].fn !== callback && evts[i].fn._ !== callback)
333          liveEvents.push(evts[i]);
334      }
335    }
336
337    // Remove event from queue to prevent memory leak
338    // Suggested by https://github.com/lazd
339    // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
340
341    (liveEvents.length)
342      ? e[name] = liveEvents
343      : delete e[name];
344
345    return this;
346  }
347};
348
349module.exports = E;
350
351},{}],8:[function(require,module,exports){
352'use strict';
353
354exports.__esModule = true;
355
356var _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; }; })();
357
358function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
359
360function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
361
362var _select = require('select');
363
364var _select2 = _interopRequireDefault(_select);
365
366/**
367 * Inner class which performs selection from either `text` or `target`
368 * properties and then executes copy or cut operations.
369 */
370
371var ClipboardAction = (function () {
372    /**
373     * @param {Object} options
374     */
375
376    function ClipboardAction(options) {
377        _classCallCheck(this, ClipboardAction);
378
379        this.resolveOptions(options);
380        this.initSelection();
381    }
382
383    /**
384     * Defines base properties passed from constructor.
385     * @param {Object} options
386     */
387
388    ClipboardAction.prototype.resolveOptions = function resolveOptions() {
389        var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
390
391        this.action = options.action;
392        this.emitter = options.emitter;
393        this.target = options.target;
394        this.text = options.text;
395        this.trigger = options.trigger;
396
397        this.selectedText = '';
398    };
399
400    /**
401     * Decides which selection strategy is going to be applied based
402     * on the existence of `text` and `target` properties.
403     */
404
405    ClipboardAction.prototype.initSelection = function initSelection() {
406        if (this.text && this.target) {
407            throw new Error('Multiple attributes declared, use either "target" or "text"');
408        } else if (this.text) {
409            this.selectFake();
410        } else if (this.target) {
411            this.selectTarget();
412        } else {
413            throw new Error('Missing required attributes, use either "target" or "text"');
414        }
415    };
416
417    /**
418     * Creates a fake textarea element, sets its value from `text` property,
419     * and makes a selection on it.
420     */
421
422    ClipboardAction.prototype.selectFake = function selectFake() {
423        var _this = this;
424
425        this.removeFake();
426
427        this.fakeHandler = document.body.addEventListener('click', function () {
428            return _this.removeFake();
429        });
430
431        this.fakeElem = document.createElement('textarea');
432        this.fakeElem.style.position = 'absolute';
433        this.fakeElem.style.left = '-9999px';
434        this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
435        this.fakeElem.setAttribute('readonly', '');
436        this.fakeElem.value = this.text;
437
438        document.body.appendChild(this.fakeElem);
439
440        this.selectedText = _select2['default'](this.fakeElem);
441        this.copyText();
442    };
443
444    /**
445     * Only removes the fake element after another click event, that way
446     * a user can hit `Ctrl+C` to copy because selection still exists.
447     */
448
449    ClipboardAction.prototype.removeFake = function removeFake() {
450        if (this.fakeHandler) {
451            document.body.removeEventListener('click');
452            this.fakeHandler = null;
453        }
454
455        if (this.fakeElem) {
456            document.body.removeChild(this.fakeElem);
457            this.fakeElem = null;
458        }
459    };
460
461    /**
462     * Selects the content from element passed on `target` property.
463     */
464
465    ClipboardAction.prototype.selectTarget = function selectTarget() {
466        this.selectedText = _select2['default'](this.target);
467        this.copyText();
468    };
469
470    /**
471     * Executes the copy operation based on the current selection.
472     */
473
474    ClipboardAction.prototype.copyText = function copyText() {
475        var succeeded = undefined;
476
477        try {
478            succeeded = document.execCommand(this.action);
479        } catch (err) {
480            succeeded = false;
481        }
482
483        this.handleResult(succeeded);
484    };
485
486    /**
487     * Fires an event based on the copy operation result.
488     * @param {Boolean} succeeded
489     */
490
491    ClipboardAction.prototype.handleResult = function handleResult(succeeded) {
492        if (succeeded) {
493            this.emitter.emit('success', {
494                action: this.action,
495                text: this.selectedText,
496                trigger: this.trigger,
497                clearSelection: this.clearSelection.bind(this)
498            });
499        } else {
500            this.emitter.emit('error', {
501                action: this.action,
502                trigger: this.trigger,
503                clearSelection: this.clearSelection.bind(this)
504            });
505        }
506    };
507
508    /**
509     * Removes current selection and focus from `target` element.
510     */
511
512    ClipboardAction.prototype.clearSelection = function clearSelection() {
513        if (this.target) {
514            this.target.blur();
515        }
516
517        window.getSelection().removeAllRanges();
518    };
519
520    /**
521     * Sets the `action` to be performed which can be either 'copy' or 'cut'.
522     * @param {String} action
523     */
524
525    /**
526     * Destroy lifecycle.
527     */
528
529    ClipboardAction.prototype.destroy = function destroy() {
530        this.removeFake();
531    };
532
533    _createClass(ClipboardAction, [{
534        key: 'action',
535        set: function set() {
536            var action = arguments.length <= 0 || arguments[0] === undefined ? 'copy' : arguments[0];
537
538            this._action = action;
539
540            if (this._action !== 'copy' && this._action !== 'cut') {
541                throw new Error('Invalid "action" value, use either "copy" or "cut"');
542            }
543        },
544
545        /**
546         * Gets the `action` property.
547         * @return {String}
548         */
549        get: function get() {
550            return this._action;
551        }
552
553        /**
554         * Sets the `target` property using an element
555         * that will be have its content copied.
556         * @param {Element} target
557         */
558    }, {
559        key: 'target',
560        set: function set(target) {
561            if (target !== undefined) {
562                if (target && typeof target === 'object' && target.nodeType === 1) {
563                    this._target = target;
564                } else {
565                    throw new Error('Invalid "target" value, use a valid Element');
566                }
567            }
568        },
569
570        /**
571         * Gets the `target` property.
572         * @return {String|HTMLElement}
573         */
574        get: function get() {
575            return this._target;
576        }
577    }]);
578
579    return ClipboardAction;
580})();
581
582exports['default'] = ClipboardAction;
583module.exports = exports['default'];
584
585},{"select":6}],9:[function(require,module,exports){
586'use strict';
587
588exports.__esModule = true;
589
590function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
591
592function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
593
594function _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; }
595
596var _clipboardAction = require('./clipboard-action');
597
598var _clipboardAction2 = _interopRequireDefault(_clipboardAction);
599
600var _tinyEmitter = require('tiny-emitter');
601
602var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);
603
604var _goodListener = require('good-listener');
605
606var _goodListener2 = _interopRequireDefault(_goodListener);
607
608/**
609 * Base class which takes one or more elements, adds event listeners to them,
610 * and instantiates a new `ClipboardAction` on each click.
611 */
612
613var Clipboard = (function (_Emitter) {
614    _inherits(Clipboard, _Emitter);
615
616    /**
617     * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
618     * @param {Object} options
619     */
620
621    function Clipboard(trigger, options) {
622        _classCallCheck(this, Clipboard);
623
624        _Emitter.call(this);
625
626        this.resolveOptions(options);
627        this.listenClick(trigger);
628    }
629
630    /**
631     * Helper function to retrieve attribute value.
632     * @param {String} suffix
633     * @param {Element} element
634     */
635
636    /**
637     * Defines if attributes would be resolved using internal setter functions
638     * or custom functions that were passed in the constructor.
639     * @param {Object} options
640     */
641
642    Clipboard.prototype.resolveOptions = function resolveOptions() {
643        var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
644
645        this.action = typeof options.action === 'function' ? options.action : this.defaultAction;
646        this.target = typeof options.target === 'function' ? options.target : this.defaultTarget;
647        this.text = typeof options.text === 'function' ? options.text : this.defaultText;
648    };
649
650    /**
651     * Adds a click event listener to the passed trigger.
652     * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
653     */
654
655    Clipboard.prototype.listenClick = function listenClick(trigger) {
656        var _this = this;
657
658        this.listener = _goodListener2['default'](trigger, 'click', function (e) {
659            return _this.onClick(e);
660        });
661    };
662
663    /**
664     * Defines a new `ClipboardAction` on each click event.
665     * @param {Event} e
666     */
667
668    Clipboard.prototype.onClick = function onClick(e) {
669        var trigger = e.delegateTarget || e.currentTarget;
670
671        if (this.clipboardAction) {
672            this.clipboardAction = null;
673        }
674
675        this.clipboardAction = new _clipboardAction2['default']({
676            action: this.action(trigger),
677            target: this.target(trigger),
678            text: this.text(trigger),
679            trigger: trigger,
680            emitter: this
681        });
682    };
683
684    /**
685     * Default `action` lookup function.
686     * @param {Element} trigger
687     */
688
689    Clipboard.prototype.defaultAction = function defaultAction(trigger) {
690        return getAttributeValue('action', trigger);
691    };
692
693    /**
694     * Default `target` lookup function.
695     * @param {Element} trigger
696     */
697
698    Clipboard.prototype.defaultTarget = function defaultTarget(trigger) {
699        var selector = getAttributeValue('target', trigger);
700
701        if (selector) {
702            return document.querySelector(selector);
703        }
704    };
705
706    /**
707     * Default `text` lookup function.
708     * @param {Element} trigger
709     */
710
711    Clipboard.prototype.defaultText = function defaultText(trigger) {
712        return getAttributeValue('text', trigger);
713    };
714
715    /**
716     * Destroy lifecycle.
717     */
718
719    Clipboard.prototype.destroy = function destroy() {
720        this.listener.destroy();
721
722        if (this.clipboardAction) {
723            this.clipboardAction.destroy();
724            this.clipboardAction = null;
725        }
726    };
727
728    return Clipboard;
729})(_tinyEmitter2['default']);
730
731function getAttributeValue(suffix, element) {
732    var attribute = 'data-clipboard-' + suffix;
733
734    if (!element.hasAttribute(attribute)) {
735        return;
736    }
737
738    return element.getAttribute(attribute);
739}
740
741exports['default'] = Clipboard;
742module.exports = exports['default'];
743
744},{"./clipboard-action":8,"good-listener":5,"tiny-emitter":7}]},{},[9])(9)
745});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.