mirror of
https://github.com/zenorocha/clipboard.js.git
synced 2023-08-10 21:12:48 +03:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e37c95121 | ||
|
|
bc9bcdd678 | ||
|
|
4c9e29a0dc | ||
|
|
bd6dc9eb9f | ||
|
|
a88bb77be4 | ||
|
|
e86dc2caa2 | ||
|
|
8392a7ba1c | ||
|
|
31e3622e17 | ||
|
|
ee1eb455f4 | ||
|
|
d50f2fb73f | ||
|
|
c8221c742d | ||
|
|
efc22cf651 | ||
|
|
4b27a72dce | ||
|
|
c12c610b22 | ||
|
|
1d772a0cbe | ||
|
|
d9254459b7 | ||
|
|
2aa163b1d0 | ||
|
|
783dc6f3cf | ||
|
|
3188ffbce3 | ||
|
|
5dba68634e | ||
|
|
a12a056ef6 | ||
|
|
cb4301658c | ||
|
|
5efcdf2810 | ||
|
|
72926580c3 | ||
|
|
4967f118fe | ||
|
|
44d59b34a2 | ||
|
|
9d6375d20e | ||
|
|
37136663df | ||
|
|
db575bb4df | ||
|
|
bb6c4c0e7c | ||
|
|
03ee9829e0 | ||
|
|
24f6e1f541 | ||
|
|
5bdfff6375 | ||
|
|
4b73122f81 | ||
|
|
171f438f22 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
lib
|
||||
npm-debug.log
|
||||
bower_components
|
||||
node_modules
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
/.*
|
||||
/bower.json
|
||||
/karma.conf.js
|
||||
/src
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "clipboard",
|
||||
"version": "1.5.0",
|
||||
"version": "1.5.8",
|
||||
"description": "Modern copy to clipboard. No Flash. Just 2kb",
|
||||
"license": "MIT",
|
||||
"main": "dist/clipboard.js",
|
||||
@@ -10,7 +10,9 @@
|
||||
"/test/",
|
||||
"/.*",
|
||||
"/bower.json",
|
||||
"/karma.conf.js"
|
||||
"/karma.conf.js",
|
||||
"/src",
|
||||
"/lib"
|
||||
],
|
||||
"keywords": [
|
||||
"clipboard",
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
</head>
|
||||
<body>
|
||||
<!-- 1. Define some markup -->
|
||||
<button id="btn" data-clipboard-text="1">Copy</button>
|
||||
<div id="btn" data-clipboard-text="1">
|
||||
<span>Copy</span>
|
||||
</div>
|
||||
|
||||
<!-- 2. Include library -->
|
||||
<script src="../dist/clipboard.min.js"></script>
|
||||
|
||||
146
dist/clipboard.js
vendored
146
dist/clipboard.js
vendored
@@ -1,5 +1,5 @@
|
||||
/*!
|
||||
* clipboard.js v1.5.0
|
||||
* clipboard.js v1.5.8
|
||||
* https://zenorocha.github.io/clipboard.js
|
||||
*
|
||||
* Licensed MIT © Zeno Rocha
|
||||
@@ -16,48 +16,7 @@ module.exports = function (element, selector, checkYoSelf) {
|
||||
}
|
||||
}
|
||||
|
||||
},{"matches-selector":2}],2:[function(require,module,exports){
|
||||
|
||||
/**
|
||||
* Element prototype.
|
||||
*/
|
||||
|
||||
var proto = Element.prototype;
|
||||
|
||||
/**
|
||||
* Vendor function.
|
||||
*/
|
||||
|
||||
var vendor = proto.matchesSelector
|
||||
|| proto.webkitMatchesSelector
|
||||
|| proto.mozMatchesSelector
|
||||
|| proto.msMatchesSelector
|
||||
|| proto.oMatchesSelector;
|
||||
|
||||
/**
|
||||
* Expose `match()`.
|
||||
*/
|
||||
|
||||
module.exports = match;
|
||||
|
||||
/**
|
||||
* Match `el` to `selector`.
|
||||
*
|
||||
* @param {Element} el
|
||||
* @param {String} selector
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function match(el, selector) {
|
||||
if (vendor) return vendor.call(el, selector);
|
||||
var nodes = el.parentNode.querySelectorAll(selector);
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
if (nodes[i] == el) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},{}],3:[function(require,module,exports){
|
||||
},{"matches-selector":5}],2:[function(require,module,exports){
|
||||
var closest = require('closest');
|
||||
|
||||
/**
|
||||
@@ -67,16 +26,17 @@ var closest = require('closest');
|
||||
* @param {String} selector
|
||||
* @param {String} type
|
||||
* @param {Function} callback
|
||||
* @param {Boolean} useCapture
|
||||
* @return {Object}
|
||||
*/
|
||||
function delegate(element, selector, type, callback) {
|
||||
function delegate(element, selector, type, callback, useCapture) {
|
||||
var listenerFn = listener.apply(this, arguments);
|
||||
|
||||
element.addEventListener(type, listenerFn);
|
||||
element.addEventListener(type, listenerFn, useCapture);
|
||||
|
||||
return {
|
||||
destroy: function() {
|
||||
element.removeEventListener(type, listenerFn);
|
||||
element.removeEventListener(type, listenerFn, useCapture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,13 +52,9 @@ function delegate(element, selector, type, callback) {
|
||||
*/
|
||||
function listener(element, selector, type, callback) {
|
||||
return function(e) {
|
||||
var delegateTarget = closest(e.target, selector, true);
|
||||
|
||||
if (delegateTarget) {
|
||||
Object.defineProperty(e, 'target', {
|
||||
value: delegateTarget
|
||||
});
|
||||
e.delegateTarget = closest(e.target, selector, true);
|
||||
|
||||
if (e.delegateTarget) {
|
||||
callback.call(element, e);
|
||||
}
|
||||
}
|
||||
@@ -106,7 +62,7 @@ function listener(element, selector, type, callback) {
|
||||
|
||||
module.exports = delegate;
|
||||
|
||||
},{"closest":1}],4:[function(require,module,exports){
|
||||
},{"closest":1}],3:[function(require,module,exports){
|
||||
/**
|
||||
* Check if argument is a HTML element.
|
||||
*
|
||||
@@ -151,13 +107,13 @@ exports.string = function(value) {
|
||||
* @param {Object} value
|
||||
* @return {Boolean}
|
||||
*/
|
||||
exports.function = function(value) {
|
||||
exports.fn = function(value) {
|
||||
var type = Object.prototype.toString.call(value);
|
||||
|
||||
return type === '[object Function]';
|
||||
};
|
||||
|
||||
},{}],5:[function(require,module,exports){
|
||||
},{}],4:[function(require,module,exports){
|
||||
var is = require('./is');
|
||||
var delegate = require('delegate');
|
||||
|
||||
@@ -179,7 +135,7 @@ function listen(target, type, callback) {
|
||||
throw new TypeError('Second argument must be a String');
|
||||
}
|
||||
|
||||
if (!is.function(callback)) {
|
||||
if (!is.fn(callback)) {
|
||||
throw new TypeError('Third argument must be a Function');
|
||||
}
|
||||
|
||||
@@ -254,17 +210,62 @@ function listenSelector(selector, type, callback) {
|
||||
|
||||
module.exports = listen;
|
||||
|
||||
},{"./is":4,"delegate":3}],6:[function(require,module,exports){
|
||||
},{"./is":3,"delegate":2}],5:[function(require,module,exports){
|
||||
|
||||
/**
|
||||
* Element prototype.
|
||||
*/
|
||||
|
||||
var proto = Element.prototype;
|
||||
|
||||
/**
|
||||
* Vendor function.
|
||||
*/
|
||||
|
||||
var vendor = proto.matchesSelector
|
||||
|| proto.webkitMatchesSelector
|
||||
|| proto.mozMatchesSelector
|
||||
|| proto.msMatchesSelector
|
||||
|| proto.oMatchesSelector;
|
||||
|
||||
/**
|
||||
* Expose `match()`.
|
||||
*/
|
||||
|
||||
module.exports = match;
|
||||
|
||||
/**
|
||||
* Match `el` to `selector`.
|
||||
*
|
||||
* @param {Element} el
|
||||
* @param {String} selector
|
||||
* @return {Boolean}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function match(el, selector) {
|
||||
if (vendor) return vendor.call(el, selector);
|
||||
var nodes = el.parentNode.querySelectorAll(selector);
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
if (nodes[i] == el) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},{}],6:[function(require,module,exports){
|
||||
function select(element) {
|
||||
var selectedText;
|
||||
|
||||
if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
|
||||
element.selectionStart = 0;
|
||||
element.selectionEnd = element.value.length;
|
||||
element.focus();
|
||||
element.setSelectionRange(0, element.value.length);
|
||||
|
||||
selectedText = element.value;
|
||||
}
|
||||
else {
|
||||
if (element.hasAttribute('contenteditable')) {
|
||||
element.focus();
|
||||
}
|
||||
|
||||
var selection = window.getSelection();
|
||||
var range = document.createRange();
|
||||
|
||||
@@ -422,6 +423,8 @@ var ClipboardAction = (function () {
|
||||
ClipboardAction.prototype.selectFake = function selectFake() {
|
||||
var _this = this;
|
||||
|
||||
var isRTL = document.documentElement.getAttribute('dir') == 'rtl';
|
||||
|
||||
this.removeFake();
|
||||
|
||||
this.fakeHandler = document.body.addEventListener('click', function () {
|
||||
@@ -429,8 +432,16 @@ var ClipboardAction = (function () {
|
||||
});
|
||||
|
||||
this.fakeElem = document.createElement('textarea');
|
||||
// Prevent zooming on iOS
|
||||
this.fakeElem.style.fontSize = '12pt';
|
||||
// Reset box model
|
||||
this.fakeElem.style.border = '0';
|
||||
this.fakeElem.style.padding = '0';
|
||||
this.fakeElem.style.margin = '0';
|
||||
// Move element out of screen horizontally
|
||||
this.fakeElem.style.position = 'absolute';
|
||||
this.fakeElem.style.left = '-9999px';
|
||||
this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px';
|
||||
// Move element to the same position vertically
|
||||
this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
|
||||
this.fakeElem.setAttribute('readonly', '');
|
||||
this.fakeElem.value = this.text;
|
||||
@@ -666,15 +677,17 @@ var Clipboard = (function (_Emitter) {
|
||||
*/
|
||||
|
||||
Clipboard.prototype.onClick = function onClick(e) {
|
||||
var trigger = e.delegateTarget || e.currentTarget;
|
||||
|
||||
if (this.clipboardAction) {
|
||||
this.clipboardAction = null;
|
||||
}
|
||||
|
||||
this.clipboardAction = new _clipboardAction2['default']({
|
||||
action: this.action(e.target),
|
||||
target: this.target(e.target),
|
||||
text: this.text(e.target),
|
||||
trigger: e.target,
|
||||
action: this.action(trigger),
|
||||
target: this.target(trigger),
|
||||
text: this.text(trigger),
|
||||
trigger: trigger,
|
||||
emitter: this
|
||||
});
|
||||
};
|
||||
@@ -726,6 +739,7 @@ var Clipboard = (function (_Emitter) {
|
||||
return Clipboard;
|
||||
})(_tinyEmitter2['default']);
|
||||
|
||||
exports['default'] = Clipboard;
|
||||
function getAttributeValue(suffix, element) {
|
||||
var attribute = 'data-clipboard-' + suffix;
|
||||
|
||||
@@ -735,9 +749,7 @@ function getAttributeValue(suffix, element) {
|
||||
|
||||
return element.getAttribute(attribute);
|
||||
}
|
||||
|
||||
exports['default'] = Clipboard;
|
||||
module.exports = exports['default'];
|
||||
|
||||
},{"./clipboard-action":8,"good-listener":5,"tiny-emitter":7}]},{},[9])(9)
|
||||
},{"./clipboard-action":8,"good-listener":4,"tiny-emitter":7}]},{},[9])(9)
|
||||
});
|
||||
4
dist/clipboard.min.js
vendored
4
dist/clipboard.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -3,10 +3,10 @@
|
||||
Package.describe({
|
||||
name: "zenorocha:clipboard",
|
||||
summary: "Modern copy to clipboard. No Flash. Just 2kb.",
|
||||
version: "1.5.0",
|
||||
version: "1.5.8",
|
||||
git: "https://github.com/zenorocha/clipboard.js"
|
||||
});
|
||||
|
||||
Package.onUse(function(api) {
|
||||
api.addFiles("dist/clipboard.min.js", "client");
|
||||
api.addFiles("dist/clipboard.js", "client");
|
||||
});
|
||||
|
||||
40
package.json
40
package.json
@@ -1,34 +1,26 @@
|
||||
{
|
||||
"name": "clipboard",
|
||||
"version": "1.5.0",
|
||||
"version": "1.5.8",
|
||||
"description": "Modern copy to clipboard. No Flash. Just 2kb",
|
||||
"repository": "zenorocha/clipboard.js",
|
||||
"license": "MIT",
|
||||
"main": "dist/clipboard.js",
|
||||
"browser": "src/clipboard.js",
|
||||
"browserify": {
|
||||
"transform": [
|
||||
[
|
||||
"babelify",
|
||||
{
|
||||
"loose": "all"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"main": "lib/clipboard.js",
|
||||
"keywords": [
|
||||
"clipboard",
|
||||
"copy",
|
||||
"cut"
|
||||
],
|
||||
"dependencies": {
|
||||
"babelify": "^6.3.0",
|
||||
"browserify": "^11.2.0",
|
||||
"good-listener": "^1.1.2",
|
||||
"select": "^1.0.3",
|
||||
"good-listener": "^1.1.6",
|
||||
"select": "^1.0.6",
|
||||
"tiny-emitter": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^5.8.29",
|
||||
"babelify": "^6.3.0",
|
||||
"bannerify": "Vekat/bannerify#feature-option",
|
||||
"browserify": "^11.2.0",
|
||||
"chai": "^3.4.1",
|
||||
"karma": "^0.13.10",
|
||||
"karma-browserify": "^4.4.0",
|
||||
"karma-chai": "^0.1.0",
|
||||
@@ -36,18 +28,18 @@
|
||||
"karma-phantomjs-launcher": "^0.2.1",
|
||||
"karma-sinon": "^1.0.4",
|
||||
"mocha": "^2.3.3",
|
||||
"phantomjs": "^1.9.18",
|
||||
"phantomjs-polyfill": "0.0.1",
|
||||
"sinon": "^1.17.2",
|
||||
"uglify-js": "^2.4.24",
|
||||
"watchify": "^3.4.0",
|
||||
"bannerify": "Vekat/bannerify#feature-option"
|
||||
"watchify": "^3.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build-debug && npm run build-min",
|
||||
"build-debug": "browserify src/clipboard.js -s Clipboard -p [bannerify --file .banner ] -o dist/clipboard.js",
|
||||
"build-debug": "browserify src/clipboard.js -s Clipboard -t [babelify --loose all] -p [bannerify --file .banner ] -o dist/clipboard.js",
|
||||
"build-min": "uglifyjs dist/clipboard.js --comments '/!/' -m screw_ie8=true -c screw_ie8=true,unused=false -o dist/clipboard.min.js",
|
||||
"build-watch": "watchify src/clipboard.js -s Clipboard -o dist/clipboard.js -v",
|
||||
"test": "npm run test-browser && npm run test-server",
|
||||
"test-browser": "karma start --single-run",
|
||||
"test-server": "mocha test/module-systems.js"
|
||||
"build-watch": "watchify src/clipboard.js -s Clipboard -t [babelify --loose all] -o dist/clipboard.js -v",
|
||||
"test": "karma start --single-run",
|
||||
"prepublish": "babel src --out-dir lib --loose all"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ new Clipboard('.btn', {
|
||||
});
|
||||
```
|
||||
|
||||
Also, with 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.
|
||||
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
|
||||
var clipboard = new Clipboard('.btn');
|
||||
|
||||
@@ -4,7 +4,7 @@ import select from 'select';
|
||||
* Inner class which performs selection from either `text` or `target`
|
||||
* properties and then executes copy or cut operations.
|
||||
*/
|
||||
class ClipboardAction {
|
||||
export default class ClipboardAction {
|
||||
/**
|
||||
* @param {Object} options
|
||||
*/
|
||||
@@ -51,13 +51,23 @@ class ClipboardAction {
|
||||
* and makes a selection on it.
|
||||
*/
|
||||
selectFake() {
|
||||
let isRTL = document.documentElement.getAttribute('dir') == 'rtl';
|
||||
|
||||
this.removeFake();
|
||||
|
||||
this.fakeHandler = document.body.addEventListener('click', () => this.removeFake());
|
||||
|
||||
this.fakeElem = document.createElement('textarea');
|
||||
// Prevent zooming on iOS
|
||||
this.fakeElem.style.fontSize = '12pt';
|
||||
// Reset box model
|
||||
this.fakeElem.style.border = '0';
|
||||
this.fakeElem.style.padding = '0';
|
||||
this.fakeElem.style.margin = '0';
|
||||
// Move element out of screen horizontally
|
||||
this.fakeElem.style.position = 'absolute';
|
||||
this.fakeElem.style.left = '-9999px';
|
||||
this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px';
|
||||
// Move element to the same position vertically
|
||||
this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
|
||||
this.fakeElem.setAttribute('readonly', '');
|
||||
this.fakeElem.value = this.text;
|
||||
@@ -192,5 +202,3 @@ class ClipboardAction {
|
||||
this.removeFake();
|
||||
}
|
||||
}
|
||||
|
||||
export default ClipboardAction;
|
||||
|
||||
@@ -6,7 +6,7 @@ import listen from 'good-listener';
|
||||
* Base class which takes one or more elements, adds event listeners to them,
|
||||
* and instantiates a new `ClipboardAction` on each click.
|
||||
*/
|
||||
class Clipboard extends Emitter {
|
||||
export default class Clipboard extends Emitter {
|
||||
/**
|
||||
* @param {String|HTMLElement|HTMLCollection|NodeList} trigger
|
||||
* @param {Object} options
|
||||
@@ -42,15 +42,17 @@ class Clipboard extends Emitter {
|
||||
* @param {Event} e
|
||||
*/
|
||||
onClick(e) {
|
||||
let trigger = e.delegateTarget || e.currentTarget;
|
||||
|
||||
if (this.clipboardAction) {
|
||||
this.clipboardAction = null;
|
||||
}
|
||||
|
||||
this.clipboardAction = new ClipboardAction({
|
||||
action : this.action(e.target),
|
||||
target : this.target(e.target),
|
||||
text : this.text(e.target),
|
||||
trigger : e.target,
|
||||
action : this.action(trigger),
|
||||
target : this.target(trigger),
|
||||
text : this.text(trigger),
|
||||
trigger : trigger,
|
||||
emitter : this
|
||||
});
|
||||
}
|
||||
@@ -111,5 +113,3 @@ function getAttributeValue(suffix, element) {
|
||||
|
||||
return element.getAttribute(attribute);
|
||||
}
|
||||
|
||||
export default Clipboard;
|
||||
|
||||
@@ -57,6 +57,19 @@ describe('ClipboardAction', () => {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
it('should set the position right style property', done => {
|
||||
// Set document direction
|
||||
document.documentElement.setAttribute('dir', 'rtl');
|
||||
|
||||
let clip = new ClipboardAction({
|
||||
emitter: new Emitter(),
|
||||
text: 'foo'
|
||||
});
|
||||
|
||||
assert.equal(clip.fakeElem.style.right, '-9999px');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#set action', () => {
|
||||
|
||||
@@ -9,8 +9,14 @@ describe('Clipboard', () => {
|
||||
global.button.setAttribute('data-clipboard-text', 'foo');
|
||||
document.body.appendChild(global.button);
|
||||
|
||||
global.span = document.createElement('span');
|
||||
global.span.innerHTML = 'bar';
|
||||
|
||||
global.button.appendChild(span);
|
||||
|
||||
global.event = {
|
||||
target: global.button
|
||||
target: global.button,
|
||||
currentTarget: global.button
|
||||
};
|
||||
});
|
||||
|
||||
@@ -63,7 +69,15 @@ describe('Clipboard', () => {
|
||||
assert.instanceOf(clipboard.clipboardAction, ClipboardAction);
|
||||
});
|
||||
|
||||
it('should throws exception target', done => {
|
||||
it('should use an event\'s currentTarget when not equal to target', () => {
|
||||
let clipboard = new Clipboard('.btn');
|
||||
let bubbledEvent = { target: global.span, currentTarget: global.button };
|
||||
|
||||
clipboard.onClick(bubbledEvent);
|
||||
assert.instanceOf(clipboard.clipboardAction, ClipboardAction);
|
||||
});
|
||||
|
||||
it('should throw an exception when target is invalid', done => {
|
||||
try {
|
||||
var clipboard = new Clipboard('.btn', {
|
||||
target: function() {
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
var assert = require('chai').assert;
|
||||
var browserify = require('browserify');
|
||||
|
||||
describe('CommonJS', function() {
|
||||
it('should import the lib in a commonjs env without babel', function(done) {
|
||||
browserify('./dist/clipboard.js').bundle(function(err) {
|
||||
assert.equal(err, null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('AMD', function() {
|
||||
// TODO: Write test case
|
||||
});
|
||||
Reference in New Issue
Block a user