UNPKG

3.73 kBJavaScriptView Raw
1import ClipboardAction from './clipboard-action';
2import Emitter from 'tiny-emitter';
3import listen from 'good-listener';
4
5/**
6 * Base class which takes one or more elements, adds event listeners to them,
7 * and instantiates a new `ClipboardAction` on each click.
8 */
9class Clipboard extends Emitter {
10 /**
11 * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
12 * @param {Object} options
13 */
14 constructor(trigger, options) {
15 super();
16
17 this.resolveOptions(options);
18 this.listenClick(trigger);
19 }
20
21 /**
22 * Defines if attributes would be resolved using internal setter functions
23 * or custom functions that were passed in the constructor.
24 * @param {Object} options
25 */
26 resolveOptions(options = {}) {
27 this.action = (typeof options.action === 'function') ? options.action : this.defaultAction;
28 this.target = (typeof options.target === 'function') ? options.target : this.defaultTarget;
29 this.text = (typeof options.text === 'function') ? options.text : this.defaultText;
30 this.container = (typeof options.container === 'object') ? options.container : document.body;
31 }
32
33 /**
34 * Adds a click event listener to the passed trigger.
35 * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
36 */
37 listenClick(trigger) {
38 this.listener = listen(trigger, 'click', (e) => this.onClick(e));
39 }
40
41 /**
42 * Defines a new `ClipboardAction` on each click event.
43 * @param {Event} e
44 */
45 onClick(e) {
46 const trigger = e.delegateTarget || e.currentTarget;
47
48 if (this.clipboardAction) {
49 this.clipboardAction = null;
50 }
51
52 this.clipboardAction = new ClipboardAction({
53 action : this.action(trigger),
54 target : this.target(trigger),
55 text : this.text(trigger),
56 container : this.container,
57 trigger : trigger,
58 emitter : this
59 });
60 }
61
62 /**
63 * Default `action` lookup function.
64 * @param {Element} trigger
65 */
66 defaultAction(trigger) {
67 return getAttributeValue('action', trigger);
68 }
69
70 /**
71 * Default `target` lookup function.
72 * @param {Element} trigger
73 */
74 defaultTarget(trigger) {
75 const selector = getAttributeValue('target', trigger);
76
77 if (selector) {
78 return document.querySelector(selector);
79 }
80 }
81
82 /**
83 * Returns the support of the given action, or all actions if no action is
84 * given.
85 * @param {String} [action]
86 */
87 static isSupported(action = ['copy', 'cut']) {
88 const actions = (typeof action === 'string') ? [action] : action;
89 let support = !!document.queryCommandSupported;
90
91 actions.forEach((action) => {
92 support = support && !!document.queryCommandSupported(action);
93 });
94
95 return support;
96 }
97
98 /**
99 * Default `text` lookup function.
100 * @param {Element} trigger
101 */
102 defaultText(trigger) {
103 return getAttributeValue('text', trigger);
104 }
105
106 /**
107 * Destroy lifecycle.
108 */
109 destroy() {
110 this.listener.destroy();
111
112 if (this.clipboardAction) {
113 this.clipboardAction.destroy();
114 this.clipboardAction = null;
115 }
116 }
117}
118
119
120/**
121 * Helper function to retrieve attribute value.
122 * @param {String} suffix
123 * @param {Element} element
124 */
125function getAttributeValue(suffix, element) {
126 const attribute = `data-clipboard-${suffix}`;
127
128 if (!element.hasAttribute(attribute)) {
129 return;
130 }
131
132 return element.getAttribute(attribute);
133}
134
135module.exports = Clipboard;