Compare commits

..

1 Commits

Author SHA1 Message Date
Zeno Rocha
0a0de9fc01 Release v1.5.3 2015-10-28 13:06:53 -07:00
11 changed files with 91 additions and 144 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "clipboard", "name": "clipboard",
"version": "1.5.8", "version": "1.5.3",
"description": "Modern copy to clipboard. No Flash. Just 2kb", "description": "Modern copy to clipboard. No Flash. Just 2kb",
"license": "MIT", "license": "MIT",
"main": "dist/clipboard.js", "main": "dist/clipboard.js",

View File

@@ -6,9 +6,7 @@
</head> </head>
<body> <body>
<!-- 1. Define some markup --> <!-- 1. Define some markup -->
<div id="btn" data-clipboard-text="1"> <button id="btn" data-clipboard-text="1">Copy</button>
<span>Copy</span>
</div>
<!-- 2. Include library --> <!-- 2. Include library -->
<script src="../dist/clipboard.min.js"></script> <script src="../dist/clipboard.min.js"></script>

145
dist/clipboard.js vendored
View File

@@ -1,5 +1,5 @@
/*! /*!
* clipboard.js v1.5.8 * clipboard.js v1.5.3
* https://zenorocha.github.io/clipboard.js * https://zenorocha.github.io/clipboard.js
* *
* Licensed MIT © Zeno Rocha * Licensed MIT © Zeno Rocha
@@ -16,7 +16,48 @@ module.exports = function (element, selector, checkYoSelf) {
} }
} }
},{"matches-selector":5}],2:[function(require,module,exports){ },{"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){
var closest = require('closest'); var closest = require('closest');
/** /**
@@ -26,17 +67,16 @@ var closest = require('closest');
* @param {String} selector * @param {String} selector
* @param {String} type * @param {String} type
* @param {Function} callback * @param {Function} callback
* @param {Boolean} useCapture
* @return {Object} * @return {Object}
*/ */
function delegate(element, selector, type, callback, useCapture) { function delegate(element, selector, type, callback) {
var listenerFn = listener.apply(this, arguments); var listenerFn = listener.apply(this, arguments);
element.addEventListener(type, listenerFn, useCapture); element.addEventListener(type, listenerFn);
return { return {
destroy: function() { destroy: function() {
element.removeEventListener(type, listenerFn, useCapture); element.removeEventListener(type, listenerFn);
} }
} }
} }
@@ -52,9 +92,13 @@ function delegate(element, selector, type, callback, useCapture) {
*/ */
function listener(element, selector, type, callback) { function listener(element, selector, type, callback) {
return function(e) { return function(e) {
e.delegateTarget = closest(e.target, selector, true); var delegateTarget = closest(e.target, selector, true);
if (delegateTarget) {
Object.defineProperty(e, 'target', {
value: delegateTarget
});
if (e.delegateTarget) {
callback.call(element, e); callback.call(element, e);
} }
} }
@@ -62,7 +106,7 @@ function listener(element, selector, type, callback) {
module.exports = delegate; module.exports = delegate;
},{"closest":1}],3:[function(require,module,exports){ },{"closest":1}],4:[function(require,module,exports){
/** /**
* Check if argument is a HTML element. * Check if argument is a HTML element.
* *
@@ -107,13 +151,13 @@ exports.string = function(value) {
* @param {Object} value * @param {Object} value
* @return {Boolean} * @return {Boolean}
*/ */
exports.fn = function(value) { exports.function = function(value) {
var type = Object.prototype.toString.call(value); var type = Object.prototype.toString.call(value);
return type === '[object Function]'; return type === '[object Function]';
}; };
},{}],4:[function(require,module,exports){ },{}],5:[function(require,module,exports){
var is = require('./is'); var is = require('./is');
var delegate = require('delegate'); var delegate = require('delegate');
@@ -135,7 +179,7 @@ function listen(target, type, callback) {
throw new TypeError('Second argument must be a String'); throw new TypeError('Second argument must be a String');
} }
if (!is.fn(callback)) { if (!is.function(callback)) {
throw new TypeError('Third argument must be a Function'); throw new TypeError('Third argument must be a Function');
} }
@@ -210,62 +254,16 @@ function listenSelector(selector, type, callback) {
module.exports = listen; module.exports = listen;
},{"./is":3,"delegate":2}],5:[function(require,module,exports){ },{"./is":4,"delegate":3}],6:[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) { function select(element) {
var selectedText; var selectedText;
if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') { if (element.nodeName === 'INPUT' || element.nodeName === 'TEXTAREA') {
element.focus(); element.select();
element.setSelectionRange(0, element.value.length);
selectedText = element.value; selectedText = element.value;
} }
else { else {
if (element.hasAttribute('contenteditable')) {
element.focus();
}
var selection = window.getSelection(); var selection = window.getSelection();
var range = document.createRange(); var range = document.createRange();
@@ -423,8 +421,6 @@ var ClipboardAction = (function () {
ClipboardAction.prototype.selectFake = function selectFake() { ClipboardAction.prototype.selectFake = function selectFake() {
var _this = this; var _this = this;
var isRTL = document.documentElement.getAttribute('dir') == 'rtl';
this.removeFake(); this.removeFake();
this.fakeHandler = document.body.addEventListener('click', function () { this.fakeHandler = document.body.addEventListener('click', function () {
@@ -432,16 +428,8 @@ var ClipboardAction = (function () {
}); });
this.fakeElem = document.createElement('textarea'); 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.position = 'absolute';
this.fakeElem.style[isRTL ? 'right' : 'left'] = '-9999px'; this.fakeElem.style.left = '-9999px';
// Move element to the same position vertically
this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px'; this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
this.fakeElem.setAttribute('readonly', ''); this.fakeElem.setAttribute('readonly', '');
this.fakeElem.value = this.text; this.fakeElem.value = this.text;
@@ -677,17 +665,15 @@ var Clipboard = (function (_Emitter) {
*/ */
Clipboard.prototype.onClick = function onClick(e) { Clipboard.prototype.onClick = function onClick(e) {
var trigger = e.delegateTarget || e.currentTarget;
if (this.clipboardAction) { if (this.clipboardAction) {
this.clipboardAction = null; this.clipboardAction = null;
} }
this.clipboardAction = new _clipboardAction2['default']({ this.clipboardAction = new _clipboardAction2['default']({
action: this.action(trigger), action: this.action(e.target),
target: this.target(trigger), target: this.target(e.target),
text: this.text(trigger), text: this.text(e.target),
trigger: trigger, trigger: e.target,
emitter: this emitter: this
}); });
}; };
@@ -739,7 +725,6 @@ var Clipboard = (function (_Emitter) {
return Clipboard; return Clipboard;
})(_tinyEmitter2['default']); })(_tinyEmitter2['default']);
exports['default'] = Clipboard;
function getAttributeValue(suffix, element) { function getAttributeValue(suffix, element) {
var attribute = 'data-clipboard-' + suffix; var attribute = 'data-clipboard-' + suffix;
@@ -749,7 +734,9 @@ function getAttributeValue(suffix, element) {
return element.getAttribute(attribute); return element.getAttribute(attribute);
} }
exports['default'] = Clipboard;
module.exports = exports['default']; module.exports = exports['default'];
},{"./clipboard-action":8,"good-listener":4,"tiny-emitter":7}]},{},[9])(9) },{"./clipboard-action":8,"good-listener":5,"tiny-emitter":7}]},{},[9])(9)
}); });

File diff suppressed because one or more lines are too long

View File

@@ -3,10 +3,10 @@
Package.describe({ Package.describe({
name: "zenorocha:clipboard", name: "zenorocha:clipboard",
summary: "Modern copy to clipboard. No Flash. Just 2kb.", summary: "Modern copy to clipboard. No Flash. Just 2kb.",
version: "1.5.8", version: "1.5.1",
git: "https://github.com/zenorocha/clipboard.js" git: "https://github.com/zenorocha/clipboard.js"
}); });
Package.onUse(function(api) { Package.onUse(function(api) {
api.addFiles("dist/clipboard.js", "client"); api.addFiles("dist/clipboard.min.js", "client");
}); });

View File

@@ -1,6 +1,6 @@
{ {
"name": "clipboard", "name": "clipboard",
"version": "1.5.8", "version": "1.5.3",
"description": "Modern copy to clipboard. No Flash. Just 2kb", "description": "Modern copy to clipboard. No Flash. Just 2kb",
"repository": "zenorocha/clipboard.js", "repository": "zenorocha/clipboard.js",
"license": "MIT", "license": "MIT",
@@ -11,16 +11,14 @@
"cut" "cut"
], ],
"dependencies": { "dependencies": {
"good-listener": "^1.1.6", "good-listener": "^1.1.2",
"select": "^1.0.6", "select": "^1.0.4",
"tiny-emitter": "^1.0.0" "tiny-emitter": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"babel": "^5.8.29", "babel": "^5.8.29",
"babelify": "^6.3.0", "babelify": "^6.3.0",
"bannerify": "Vekat/bannerify#feature-option",
"browserify": "^11.2.0", "browserify": "^11.2.0",
"chai": "^3.4.1",
"karma": "^0.13.10", "karma": "^0.13.10",
"karma-browserify": "^4.4.0", "karma-browserify": "^4.4.0",
"karma-chai": "^0.1.0", "karma-chai": "^0.1.0",
@@ -28,11 +26,10 @@
"karma-phantomjs-launcher": "^0.2.1", "karma-phantomjs-launcher": "^0.2.1",
"karma-sinon": "^1.0.4", "karma-sinon": "^1.0.4",
"mocha": "^2.3.3", "mocha": "^2.3.3",
"phantomjs": "^1.9.18",
"phantomjs-polyfill": "0.0.1", "phantomjs-polyfill": "0.0.1",
"sinon": "^1.17.2",
"uglify-js": "^2.4.24", "uglify-js": "^2.4.24",
"watchify": "^3.4.0" "watchify": "^3.4.0",
"bannerify": "Vekat/bannerify#feature-option"
}, },
"scripts": { "scripts": {
"build": "npm run build-debug && npm run build-min", "build": "npm run build-debug && npm run build-min",

View File

@@ -151,7 +151,7 @@ new Clipboard('.btn', {
}); });
``` ```
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. 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.
```js ```js
var clipboard = new Clipboard('.btn'); var clipboard = new Clipboard('.btn');

View File

@@ -4,7 +4,7 @@ import select from 'select';
* Inner class which performs selection from either `text` or `target` * Inner class which performs selection from either `text` or `target`
* properties and then executes copy or cut operations. * properties and then executes copy or cut operations.
*/ */
export default class ClipboardAction { class ClipboardAction {
/** /**
* @param {Object} options * @param {Object} options
*/ */
@@ -51,23 +51,13 @@ export default class ClipboardAction {
* and makes a selection on it. * and makes a selection on it.
*/ */
selectFake() { selectFake() {
let isRTL = document.documentElement.getAttribute('dir') == 'rtl';
this.removeFake(); this.removeFake();
this.fakeHandler = document.body.addEventListener('click', () => this.removeFake()); this.fakeHandler = document.body.addEventListener('click', () => this.removeFake());
this.fakeElem = document.createElement('textarea'); 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.position = 'absolute';
this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px'; this.fakeElem.style.left = '-9999px';
// Move element to the same position vertically
this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px'; this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
this.fakeElem.setAttribute('readonly', ''); this.fakeElem.setAttribute('readonly', '');
this.fakeElem.value = this.text; this.fakeElem.value = this.text;
@@ -202,3 +192,5 @@ export default class ClipboardAction {
this.removeFake(); this.removeFake();
} }
} }
export default ClipboardAction;

View File

@@ -6,7 +6,7 @@ import listen from 'good-listener';
* Base class which takes one or more elements, adds event listeners to them, * Base class which takes one or more elements, adds event listeners to them,
* and instantiates a new `ClipboardAction` on each click. * and instantiates a new `ClipboardAction` on each click.
*/ */
export default class Clipboard extends Emitter { class Clipboard extends Emitter {
/** /**
* @param {String|HTMLElement|HTMLCollection|NodeList} trigger * @param {String|HTMLElement|HTMLCollection|NodeList} trigger
* @param {Object} options * @param {Object} options
@@ -42,17 +42,15 @@ export default class Clipboard extends Emitter {
* @param {Event} e * @param {Event} e
*/ */
onClick(e) { onClick(e) {
let trigger = e.delegateTarget || e.currentTarget;
if (this.clipboardAction) { if (this.clipboardAction) {
this.clipboardAction = null; this.clipboardAction = null;
} }
this.clipboardAction = new ClipboardAction({ this.clipboardAction = new ClipboardAction({
action : this.action(trigger), action : this.action(e.target),
target : this.target(trigger), target : this.target(e.target),
text : this.text(trigger), text : this.text(e.target),
trigger : trigger, trigger : e.target,
emitter : this emitter : this
}); });
} }
@@ -113,3 +111,5 @@ function getAttributeValue(suffix, element) {
return element.getAttribute(attribute); return element.getAttribute(attribute);
} }
export default Clipboard;

View File

@@ -57,19 +57,6 @@ describe('ClipboardAction', () => {
done(); 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', () => { describe('#set action', () => {

View File

@@ -9,14 +9,8 @@ describe('Clipboard', () => {
global.button.setAttribute('data-clipboard-text', 'foo'); global.button.setAttribute('data-clipboard-text', 'foo');
document.body.appendChild(global.button); document.body.appendChild(global.button);
global.span = document.createElement('span');
global.span.innerHTML = 'bar';
global.button.appendChild(span);
global.event = { global.event = {
target: global.button, target: global.button
currentTarget: global.button
}; };
}); });
@@ -69,15 +63,7 @@ describe('Clipboard', () => {
assert.instanceOf(clipboard.clipboardAction, ClipboardAction); assert.instanceOf(clipboard.clipboardAction, ClipboardAction);
}); });
it('should use an event\'s currentTarget when not equal to target', () => { it('should throws exception target', done => {
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 { try {
var clipboard = new Clipboard('.btn', { var clipboard = new Clipboard('.btn', {
target: function() { target: function() {