diff --git a/dist/clipboard.js b/dist/clipboard.js index f81e8fe6..75b6af35 100644 --- a/dist/clipboard.js +++ b/dist/clipboard.js @@ -10,7 +10,7 @@ var DOCUMENT_NODE_TYPE = 9; /** * A polyfill for Element.matches() */ -if (Element && !Element.prototype.matches) { +if (typeof Element !== 'undefined' && !Element.prototype.matches) { var proto = Element.prototype; proto.matches = proto.matchesSelector || @@ -420,7 +420,6 @@ module.exports = E; var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; this.action = options.action; - this.container = options.container; this.emitter = options.emitter; this.target = options.target; this.text = options.text; @@ -449,7 +448,7 @@ module.exports = E; this.fakeHandlerCallback = function () { return _this.removeFake(); }; - this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true; + this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || true; this.fakeElem = document.createElement('textarea'); // Prevent zooming on iOS @@ -468,7 +467,7 @@ module.exports = E; this.fakeElem.setAttribute('readonly', ''); this.fakeElem.value = this.text; - this.container.appendChild(this.fakeElem); + document.body.appendChild(this.fakeElem); this.selectedText = (0, _select2.default)(this.fakeElem); this.copyText(); @@ -477,13 +476,13 @@ module.exports = E; key: 'removeFake', value: function removeFake() { if (this.fakeHandler) { - this.container.removeEventListener('click', this.fakeHandlerCallback); + document.body.removeEventListener('click', this.fakeHandlerCallback); this.fakeHandler = null; this.fakeHandlerCallback = null; } if (this.fakeElem) { - this.container.removeChild(this.fakeElem); + document.body.removeChild(this.fakeElem); this.fakeElem = null; } } @@ -602,12 +601,6 @@ module.exports = E; }; } - var _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; - }; - function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); @@ -688,7 +681,6 @@ module.exports = E; this.action = typeof options.action === 'function' ? options.action : this.defaultAction; this.target = typeof options.target === 'function' ? options.target : this.defaultTarget; this.text = typeof options.text === 'function' ? options.text : this.defaultText; - this.container = _typeof(options.container) === 'object' ? options.container : document.body; } }, { key: 'listenClick', @@ -712,7 +704,6 @@ module.exports = E; action: this.action(trigger), target: this.target(trigger), text: this.text(trigger), - container: this.container, trigger: trigger, emitter: this }); diff --git a/dist/clipboard.min.js b/dist/clipboard.min.js index 1a9727de..1993676f 100644 --- a/dist/clipboard.min.js +++ b/dist/clipboard.min.js @@ -4,4 +4,4 @@ * * Licensed MIT © Zeno Rocha */ -!function(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,e.Clipboard=t()}}(function(){var t,e,n;return function t(e,n,o){function i(a,c){if(!n[a]){if(!e[a]){var l="function"==typeof require&&require;if(!c&&l)return l(a,!0);if(r)return r(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var s=n[a]={exports:{}};e[a][0].call(s.exports,function(t){var n=e[a][1][t];return i(n?n:t)},s,s.exports,t,e,n,o)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a0&&void 0!==arguments[0]?arguments[0]:{};this.action=e.action,this.container=e.container,this.emitter=e.emitter,this.target=e.target,this.text=e.text,this.trigger=e.trigger,this.selectedText=""}},{key:"initSelection",value:function t(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function t(){var e=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return e.removeFake()},this.fakeHandler=this.container.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px";var o=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=o+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,this.container.appendChild(this.fakeElem),this.selectedText=(0,i.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function t(){this.fakeHandler&&(this.container.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(this.container.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function t(){this.selectedText=(0,i.default)(this.target),this.copyText()}},{key:"copyText",value:function t(){var e=void 0;try{e=document.execCommand(this.action)}catch(t){e=!1}this.handleResult(e)}},{key:"handleResult",value:function t(e){this.emitter.emit(e?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function t(){this.target&&this.target.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function t(){this.removeFake()}},{key:"action",set:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=e,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function t(){return this._action}},{key:"target",set:function t(e){if(void 0!==e){if(!e||"object"!==("undefined"==typeof e?"undefined":r(e))||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=e}},get:function t(){return this._target}}]),t}();t.exports=c})},{select:5}],8:[function(e,n,o){!function(i,r){if("function"==typeof t&&t.amd)t(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if("undefined"!=typeof o)r(n,e("./clipboard-action"),e("tiny-emitter"),e("good-listener"));else{var a={exports:{}};r(a,i.clipboardAction,i.tinyEmitter,i.goodListener),i.clipboard=a.exports}}(this,function(t,e,n,o){"use strict";function i(t){return t&&t.__esModule?t:{default:t}}function r(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function c(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}function l(t,e){var n="data-clipboard-"+t;if(e.hasAttribute(n))return e.getAttribute(n)}var u=i(e),s=i(n),f=i(o),d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},h=function(){function t(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof e.action?e.action:this.defaultAction,this.target="function"==typeof e.target?e.target:this.defaultTarget,this.text="function"==typeof e.text?e.text:this.defaultText,this.container="object"===d(e.container)?e.container:document.body}},{key:"listenClick",value:function t(e){var n=this;this.listener=(0,f.default)(e,"click",function(t){return n.onClick(t)})}},{key:"onClick",value:function t(e){var n=e.delegateTarget||e.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new u.default({action:this.action(n),target:this.target(n),text:this.text(n),container:this.container,trigger:n,emitter:this})}},{key:"defaultAction",value:function t(e){return l("action",e)}},{key:"defaultTarget",value:function t(e){var n=l("target",e);if(n)return document.querySelector(n)}},{key:"defaultText",value:function t(e){return l("text",e)}},{key:"destroy",value:function t(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function t(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],n="string"==typeof e?[e]:e,o=!!document.queryCommandSupported;return n.forEach(function(t){o=o&&!!document.queryCommandSupported(t)}),o}}]),e}(s.default);t.exports=p})},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)}); \ No newline at end of file +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.Clipboard=e()}}(function(){var e,t,n;return function e(t,n,o){function i(a,c){if(!n[a]){if(!t[a]){var l="function"==typeof require&&require;if(!c&&l)return l(a,!0);if(r)return r(a,!0);var u=new Error("Cannot find module '"+a+"'");throw u.code="MODULE_NOT_FOUND",u}var s=n[a]={exports:{}};t[a][0].call(s.exports,function(e){var n=t[a][1][e];return i(n?n:e)},s,s.exports,e,t,n,o)}return n[a].exports}for(var r="function"==typeof require&&require,a=0;a0&&void 0!==arguments[0]?arguments[0]:{};this.action=t.action,this.emitter=t.emitter,this.target=t.target,this.text=t.text,this.trigger=t.trigger,this.selectedText=""}},{key:"initSelection",value:function e(){this.text?this.selectFake():this.target&&this.selectTarget()}},{key:"selectFake",value:function e(){var t=this,n="rtl"==document.documentElement.getAttribute("dir");this.removeFake(),this.fakeHandlerCallback=function(){return t.removeFake()},this.fakeHandler=document.body.addEventListener("click",this.fakeHandlerCallback)||!0,this.fakeElem=document.createElement("textarea"),this.fakeElem.style.fontSize="12pt",this.fakeElem.style.border="0",this.fakeElem.style.padding="0",this.fakeElem.style.margin="0",this.fakeElem.style.position="absolute",this.fakeElem.style[n?"right":"left"]="-9999px";var o=window.pageYOffset||document.documentElement.scrollTop;this.fakeElem.style.top=o+"px",this.fakeElem.setAttribute("readonly",""),this.fakeElem.value=this.text,document.body.appendChild(this.fakeElem),this.selectedText=(0,i.default)(this.fakeElem),this.copyText()}},{key:"removeFake",value:function e(){this.fakeHandler&&(document.body.removeEventListener("click",this.fakeHandlerCallback),this.fakeHandler=null,this.fakeHandlerCallback=null),this.fakeElem&&(document.body.removeChild(this.fakeElem),this.fakeElem=null)}},{key:"selectTarget",value:function e(){this.selectedText=(0,i.default)(this.target),this.copyText()}},{key:"copyText",value:function e(){var t=void 0;try{t=document.execCommand(this.action)}catch(e){t=!1}this.handleResult(t)}},{key:"handleResult",value:function e(t){this.emitter.emit(t?"success":"error",{action:this.action,text:this.selectedText,trigger:this.trigger,clearSelection:this.clearSelection.bind(this)})}},{key:"clearSelection",value:function e(){this.target&&this.target.blur(),window.getSelection().removeAllRanges()}},{key:"destroy",value:function e(){this.removeFake()}},{key:"action",set:function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"copy";if(this._action=t,"copy"!==this._action&&"cut"!==this._action)throw new Error('Invalid "action" value, use either "copy" or "cut"')},get:function e(){return this._action}},{key:"target",set:function e(t){if(void 0!==t){if(!t||"object"!==("undefined"==typeof t?"undefined":r(t))||1!==t.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===this.action&&t.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===this.action&&(t.hasAttribute("readonly")||t.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes');this._target=t}},get:function e(){return this._target}}]),e}();e.exports=c})},{select:5}],8:[function(t,n,o){!function(i,r){if("function"==typeof e&&e.amd)e(["module","./clipboard-action","tiny-emitter","good-listener"],r);else if("undefined"!=typeof o)r(n,t("./clipboard-action"),t("tiny-emitter"),t("good-listener"));else{var a={exports:{}};r(a,i.clipboardAction,i.tinyEmitter,i.goodListener),i.clipboard=a.exports}}(this,function(e,t,n,o){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function a(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function c(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t){var n="data-clipboard-"+e;if(t.hasAttribute(n))return t.getAttribute(n)}var u=i(t),s=i(n),f=i(o),d=function(){function e(e,t){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText}},{key:"listenClick",value:function e(t){var n=this;this.listener=(0,f.default)(t,"click",function(e){return n.onClick(e)})}},{key:"onClick",value:function e(t){var n=t.delegateTarget||t.currentTarget;this.clipboardAction&&(this.clipboardAction=null),this.clipboardAction=new u.default({action:this.action(n),target:this.target(n),text:this.text(n),trigger:n,emitter:this})}},{key:"defaultAction",value:function e(t){return l("action",t)}},{key:"defaultTarget",value:function e(t){var n=l("target",t);if(n)return document.querySelector(n)}},{key:"defaultText",value:function e(t){return l("text",t)}},{key:"destroy",value:function e(){this.listener.destroy(),this.clipboardAction&&(this.clipboardAction.destroy(),this.clipboardAction=null)}}],[{key:"isSupported",value:function e(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:["copy","cut"],n="string"==typeof t?[t]:t,o=!!document.queryCommandSupported;return n.forEach(function(e){o=o&&!!document.queryCommandSupported(e)}),o}}]),t}(s.default);e.exports=h})},{"./clipboard-action":7,"good-listener":4,"tiny-emitter":6}]},{},[8])(8)}); \ No newline at end of file diff --git a/readme.md b/readme.md index 1dc1d891..fb16becf 100644 --- a/readme.md +++ b/readme.md @@ -145,15 +145,6 @@ new Clipboard('.btn', { }); ``` -For use in bootstrap modals or with any other library that changes the focus you'll want to set the focused element as the `container` value. -See [Issue #155 (comment)](https://github.com/zenorocha/clipboard.js/issues/155#issuecomment-273124130) - -```js -new Clipboard('.btn', { - container: document.getElementById('#modal') -}); -``` - Also, if you are working with single page apps, you may want to manage the lifecycle of the DOM more precisely. Here's how you clean up the events and objects that we create. ```js diff --git a/src/clipboard-action.js b/src/clipboard-action.js index ea2aa21a..aa5e3ad5 100644 --- a/src/clipboard-action.js +++ b/src/clipboard-action.js @@ -18,12 +18,11 @@ class ClipboardAction { * @param {Object} options */ resolveOptions(options = {}) { - this.action = options.action; - this.container = options.container; - this.emitter = options.emitter; - this.target = options.target; - this.text = options.text; - this.trigger = options.trigger; + this.action = options.action; + this.emitter = options.emitter; + this.target = options.target; + this.text = options.text; + this.trigger = options.trigger; this.selectedText = ''; } @@ -51,7 +50,7 @@ class ClipboardAction { this.removeFake(); this.fakeHandlerCallback = () => this.removeFake(); - this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true; + this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || true; this.fakeElem = document.createElement('textarea'); // Prevent zooming on iOS @@ -70,7 +69,7 @@ class ClipboardAction { this.fakeElem.setAttribute('readonly', ''); this.fakeElem.value = this.text; - this.container.appendChild(this.fakeElem); + document.body.appendChild(this.fakeElem); this.selectedText = select(this.fakeElem); this.copyText(); @@ -82,13 +81,13 @@ class ClipboardAction { */ removeFake() { if (this.fakeHandler) { - this.container.removeEventListener('click', this.fakeHandlerCallback); + document.body.removeEventListener('click', this.fakeHandlerCallback); this.fakeHandler = null; this.fakeHandlerCallback = null; } if (this.fakeElem) { - this.container.removeChild(this.fakeElem); + document.body.removeChild(this.fakeElem); this.fakeElem = null; } } diff --git a/src/clipboard.js b/src/clipboard.js index 08ee3c83..c8417fcf 100644 --- a/src/clipboard.js +++ b/src/clipboard.js @@ -24,10 +24,9 @@ class Clipboard extends Emitter { * @param {Object} options */ resolveOptions(options = {}) { - this.action = (typeof options.action === 'function') ? options.action : this.defaultAction; - this.target = (typeof options.target === 'function') ? options.target : this.defaultTarget; - this.text = (typeof options.text === 'function') ? options.text : this.defaultText; - this.container = (typeof options.container === 'object') ? options.container : document.body; + this.action = (typeof options.action === 'function') ? options.action : this.defaultAction; + this.target = (typeof options.target === 'function') ? options.target : this.defaultTarget; + this.text = (typeof options.text === 'function') ? options.text : this.defaultText; } /** @@ -50,12 +49,11 @@ class Clipboard extends Emitter { } this.clipboardAction = new ClipboardAction({ - action : this.action(trigger), - target : this.target(trigger), - text : this.text(trigger), - container : this.container, - trigger : trigger, - emitter : this + action : this.action(trigger), + target : this.target(trigger), + text : this.text(trigger), + trigger, + emitter : this }); } diff --git a/test/clipboard-action.js b/test/clipboard-action.js index 8a3133c9..d749233b 100644 --- a/test/clipboard-action.js +++ b/test/clipboard-action.js @@ -22,12 +22,10 @@ describe('ClipboardAction', () => { it('should set base properties', () => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, text: 'foo' }); assert.property(clip, 'action'); - assert.property(clip, 'container'); assert.property(clip, 'emitter'); assert.property(clip, 'target'); assert.property(clip, 'text'); @@ -43,7 +41,6 @@ describe('ClipboardAction', () => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, text: 'foo' }); @@ -85,7 +82,6 @@ describe('ClipboardAction', () => { it('should create a fake element and select its value', () => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, text: 'blah' }); @@ -97,7 +93,6 @@ describe('ClipboardAction', () => { it('should remove a temporary fake element', () => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, text: 'blah' }); @@ -111,7 +106,6 @@ describe('ClipboardAction', () => { it('should select text from editable element', () => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, target: document.querySelector('#input') }); @@ -121,7 +115,6 @@ describe('ClipboardAction', () => { it('should select text from non-editable element', () => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, target: document.querySelector('#paragraph') }); @@ -173,7 +166,6 @@ describe('ClipboardAction', () => { it('should fire a success event with certain properties', done => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, target: document.querySelector('#input') }); @@ -192,7 +184,6 @@ describe('ClipboardAction', () => { it('should fire a error event with certain properties', done => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, target: document.querySelector('#input') }); @@ -212,7 +203,6 @@ describe('ClipboardAction', () => { it('should remove focus from target and text selection', () => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, target: document.querySelector('#input') }); @@ -230,7 +220,6 @@ describe('ClipboardAction', () => { it('should destroy an existing fake element', () => { let clip = new ClipboardAction({ emitter: new Emitter(), - container: document.body, text: 'blah' }); diff --git a/test/clipboard.js b/test/clipboard.js index 9b54932d..77e0214d 100644 --- a/test/clipboard.js +++ b/test/clipboard.js @@ -52,20 +52,6 @@ describe('Clipboard', () => { assert.equal(global.fn, clipboard.text); }); - - it('should set container as an object', () => { - let clipboard = new Clipboard('.btn', { - container: document.body - }); - - assert.equal(document.body, clipboard.container); - }); - - it('should set container as body by default', () => { - let clipboard = new Clipboard('.btn'); - - assert.equal(document.body, clipboard.container); - }); }); describe('#listenClick', () => {