Compare commits

...

13 Commits
v1.6.0 ... 2.0

Author SHA1 Message Date
Lucas Bento
0c3bce265f Fix GitHub Primer tooltips link (#479) 2017-10-16 07:25:57 -07:00
Zeno Rocha
3c0dfe5a38 Adds docs on tooltips #423 2017-06-30 16:30:30 -03:00
Nathan
f960b0d20a use only ID name for DOM (#431) 2017-06-30 15:52:07 -03:00
Zeno Rocha
b6e6b80ab0 Release v1.7.1 2017-05-29 16:57:52 -07:00
Patrick H. Lauke
a55c9ac513 Move focus to trigger instead of simply blur()ing (#419)
blur() results in a loss/reset of keyboard focus, meaning keyboard users usually get thrown right back to the start of the page. Instead, this moves focus back to the trigger (which had the focus when the trigger was activated).
As with the proposed fix in https://github.com/zenorocha/clipboard.js/pull/418 this obviously results in the focus styles (like the default outline, unless suppressed) being applied to the trigger (see the related PR for rationale and future fix using `:focus-ring`)
2017-05-29 16:54:55 -07:00
Zeno Rocha
39e622456c Release v1.7.0 2017-05-29 14:43:41 -07:00
Zeno Rocha
f8c322f163 Reviews text from #368 2017-05-29 14:20:36 -07:00
Peder Johnsen
f42b57067d Container option (#368)
* Allow container option to fix bugs related to bootstrap modals etc.

* Updated readme to reflect addition of container option

* Name link

* Removed test log

* Remove unwanted whitespace

* Refactored description
2017-05-29 14:17:26 -07:00
Zeno Rocha
4065080a17 Removes bower notes from docs 2017-05-22 13:31:36 -07:00
Gabriel Kalani
5ab50475e0 ES6 refactor (#409)
* little fix

* little fix /2

* test/clipboard.js refactored

* emitter: emitter --> emitter

* Examples in ES6

* es6

* back to original code

* script > npm test

* script > npm test not necessary

* updating modules

* removing export default
2017-05-02 21:34:18 -07:00
Zeno Rocha
e1394b3b8c Adds bonus section 2017-05-01 09:17:35 -07:00
Zeno Rocha
f59d4e6b4d Release v1.6.1 2017-02-28 09:58:40 -08:00
Zeno Rocha
9ddff7e591 Prevents Node env from throwing an error 2017-02-28 09:57:36 -08:00
10 changed files with 122 additions and 68 deletions

View File

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

30
dist/clipboard.js vendored
View File

@@ -1,5 +1,5 @@
/*!
* clipboard.js v1.6.0
* clipboard.js v1.7.1
* https://zenorocha.github.io/clipboard.js
*
* Licensed MIT © Zeno Rocha
@@ -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 ||
@@ -29,7 +29,10 @@ if (Element && !Element.prototype.matches) {
*/
function closest (element, selector) {
while (element && element.nodeType !== DOCUMENT_NODE_TYPE) {
if (element.matches(selector)) return element;
if (typeof element.matches === 'function' &&
element.matches(selector)) {
return element;
}
element = element.parentNode;
}
}
@@ -420,6 +423,7 @@ 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;
@@ -448,7 +452,7 @@ module.exports = E;
this.fakeHandlerCallback = function () {
return _this.removeFake();
};
this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || true;
this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true;
this.fakeElem = document.createElement('textarea');
// Prevent zooming on iOS
@@ -467,7 +471,7 @@ module.exports = E;
this.fakeElem.setAttribute('readonly', '');
this.fakeElem.value = this.text;
document.body.appendChild(this.fakeElem);
this.container.appendChild(this.fakeElem);
this.selectedText = (0, _select2.default)(this.fakeElem);
this.copyText();
@@ -476,13 +480,13 @@ module.exports = E;
key: 'removeFake',
value: function removeFake() {
if (this.fakeHandler) {
document.body.removeEventListener('click', this.fakeHandlerCallback);
this.container.removeEventListener('click', this.fakeHandlerCallback);
this.fakeHandler = null;
this.fakeHandlerCallback = null;
}
if (this.fakeElem) {
document.body.removeChild(this.fakeElem);
this.container.removeChild(this.fakeElem);
this.fakeElem = null;
}
}
@@ -518,8 +522,8 @@ module.exports = E;
}, {
key: 'clearSelection',
value: function clearSelection() {
if (this.target) {
this.target.blur();
if (this.trigger) {
this.trigger.focus();
}
window.getSelection().removeAllRanges();
@@ -601,6 +605,12 @@ 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");
@@ -681,6 +691,7 @@ 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',
@@ -704,6 +715,7 @@ module.exports = E;
action: this.action(trigger),
target: this.target(trigger),
text: this.text(trigger),
container: this.container,
trigger: trigger,
emitter: this
});

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
Package.describe({
name: "zenorocha:clipboard",
summary: "Modern copy to clipboard. No Flash. Just 2kb.",
version: "1.6.0",
version: "1.7.1",
git: "https://github.com/zenorocha/clipboard.js"
});

View File

@@ -1,6 +1,6 @@
{
"name": "clipboard",
"version": "1.6.0",
"version": "1.7.1",
"description": "Modern copy to clipboard. No Flash. Just 2kb",
"repository": "zenorocha/clipboard.js",
"license": "MIT",
@@ -11,31 +11,31 @@
"cut"
],
"dependencies": {
"good-listener": "^1.2.0",
"good-listener": "^1.2.2",
"select": "^1.1.2",
"tiny-emitter": "^1.0.0"
"tiny-emitter": "^2.0.0"
},
"devDependencies": {
"babel-cli": "^6.5.1",
"babel-core": "^6.5.2",
"babel-plugin-transform-es2015-modules-umd": "^6.5.0",
"babel-preset-es2015": "^6.5.0",
"babelify": "^7.2.0",
"babel-cli": "^6.24.1",
"babel-core": "^6.24.1",
"babel-plugin-transform-es2015-modules-umd": "^6.24.1",
"babel-preset-es2015": "^6.24.1",
"babelify": "^7.3.0",
"bannerify": "Vekat/bannerify#feature-option",
"browserify": "^13.0.0",
"chai": "^3.4.1",
"install": "^0.8.1",
"karma": "^1.3.0",
"karma-browserify": "^5.0.1",
"browserify": "^14.3.0",
"chai": "^3.5.0",
"install": "^0.9.6",
"karma": "^1.6.0",
"karma-browserify": "^5.1.1",
"karma-chai": "^0.1.0",
"karma-mocha": "^1.2.0",
"karma-phantomjs-launcher": "^1.0.0",
"karma-sinon": "^1.0.4",
"mocha": "^3.1.2",
"phantomjs-prebuilt": "^2.1.4",
"sinon": "^1.17.2",
"uglify-js": "^2.4.24",
"watchify": "^3.4.0"
"karma-mocha": "^1.3.0",
"karma-phantomjs-launcher": "^1.0.4",
"karma-sinon": "^1.0.5",
"mocha": "^3.3.0",
"phantomjs-prebuilt": "^2.1.14",
"sinon": "^2.2.0",
"uglify-js": "^2.8.22",
"watchify": "^3.9.0"
},
"scripts": {
"build": "npm run build-debug && npm run build-min",

View File

@@ -21,13 +21,7 @@ You can get it on npm.
npm install clipboard --save
```
Or bower, too.
```
bower install clipboard --save
```
If you're not into package management, just [download a ZIP](https://github.com/zenorocha/clipboard.js/archive/master.zip) file.
Or if you're not into package management, just [download a ZIP](https://github.com/zenorocha/clipboard.js/archive/master.zip) file.
## Setup
@@ -125,7 +119,13 @@ clipboard.on('error', function(e) {
});
```
For a live demonstration, open this [site](https://clipboardjs.com/) and just your console :)
For a live demonstration, go to this [site](https://clipboardjs.com/) and open your console.
## Tooltips
Each application has different design needs, that's why clipboard.js does not include any CSS or built-in tooltip solution.
The tooltips you see on the [demo site](https://clipboardjs.com/) were built using [GitHub's Primer](https://github.com/primer/primer-css/tree/master/modules/primer-tooltips). You may want to check that out if you're looking for a similar look and feel.
## Advanced Options
@@ -151,6 +151,14 @@ 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.
```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
@@ -170,6 +178,12 @@ The good news is that clipboard.js gracefully degrades if you need to support ol
You can also check if clipboard.js is supported or not by running `Clipboard.isSupported()`, that way you can hide copy/cut buttons from the UI.
## Bonus
A browser extension that adds a "copy to clipboard" button to every code block on *GitHub, MDN, Gist, StackOverflow, StackExchange, npm, and even Medium.*
Install for [Chrome](https://chrome.google.com/webstore/detail/codecopy/fkbfebkcoelajmhanocgppanfoojcdmg) and [Firefox](https://addons.mozilla.org/en-US/firefox/addon/codecopy/).
## License
[MIT License](http://zenorocha.mit-license.org/) © Zeno Rocha

View File

@@ -18,11 +18,12 @@ class ClipboardAction {
* @param {Object} options
*/
resolveOptions(options = {}) {
this.action = options.action;
this.emitter = options.emitter;
this.target = options.target;
this.text = options.text;
this.trigger = options.trigger;
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.selectedText = '';
}
@@ -50,7 +51,7 @@ class ClipboardAction {
this.removeFake();
this.fakeHandlerCallback = () => this.removeFake();
this.fakeHandler = document.body.addEventListener('click', this.fakeHandlerCallback) || true;
this.fakeHandler = this.container.addEventListener('click', this.fakeHandlerCallback) || true;
this.fakeElem = document.createElement('textarea');
// Prevent zooming on iOS
@@ -64,12 +65,12 @@ class ClipboardAction {
this.fakeElem.style[ isRTL ? 'right' : 'left' ] = '-9999px';
// Move element to the same position vertically
let yPosition = window.pageYOffset || document.documentElement.scrollTop;
this.fakeElem.style.top = yPosition + 'px';
this.fakeElem.style.top = `${yPosition}px`;
this.fakeElem.setAttribute('readonly', '');
this.fakeElem.value = this.text;
document.body.appendChild(this.fakeElem);
this.container.appendChild(this.fakeElem);
this.selectedText = select(this.fakeElem);
this.copyText();
@@ -81,13 +82,13 @@ class ClipboardAction {
*/
removeFake() {
if (this.fakeHandler) {
document.body.removeEventListener('click', this.fakeHandlerCallback);
this.container.removeEventListener('click', this.fakeHandlerCallback);
this.fakeHandler = null;
this.fakeHandlerCallback = null;
}
if (this.fakeElem) {
document.body.removeChild(this.fakeElem);
this.container.removeChild(this.fakeElem);
this.fakeElem = null;
}
}
@@ -130,11 +131,11 @@ class ClipboardAction {
}
/**
* Removes current selection and focus from `target` element.
* Moves focus away from `target` and back to the trigger, removes current selection.
*/
clearSelection() {
if (this.target) {
this.target.blur();
if (this.trigger) {
this.trigger.focus();
}
window.getSelection().removeAllRanges();

View File

@@ -24,9 +24,10 @@ 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.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;
}
/**
@@ -49,11 +50,12 @@ class Clipboard extends Emitter {
}
this.clipboardAction = new ClipboardAction({
action : this.action(trigger),
target : this.target(trigger),
text : this.text(trigger),
trigger : trigger,
emitter : this
action : this.action(trigger),
target : this.target(trigger),
text : this.text(trigger),
container : this.container,
trigger : trigger,
emitter : this
});
}

View File

@@ -22,10 +22,12 @@ 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');
@@ -41,6 +43,7 @@ describe('ClipboardAction', () => {
let clip = new ClipboardAction({
emitter: new Emitter(),
container: document.body,
text: 'foo'
});
@@ -82,6 +85,7 @@ describe('ClipboardAction', () => {
it('should create a fake element and select its value', () => {
let clip = new ClipboardAction({
emitter: new Emitter(),
container: document.body,
text: 'blah'
});
@@ -93,6 +97,7 @@ describe('ClipboardAction', () => {
it('should remove a temporary fake element', () => {
let clip = new ClipboardAction({
emitter: new Emitter(),
container: document.body,
text: 'blah'
});
@@ -106,6 +111,7 @@ describe('ClipboardAction', () => {
it('should select text from editable element', () => {
let clip = new ClipboardAction({
emitter: new Emitter(),
container: document.body,
target: document.querySelector('#input')
});
@@ -115,6 +121,7 @@ describe('ClipboardAction', () => {
it('should select text from non-editable element', () => {
let clip = new ClipboardAction({
emitter: new Emitter(),
container: document.body,
target: document.querySelector('#paragraph')
});
@@ -141,7 +148,7 @@ describe('ClipboardAction', () => {
});
let clip = new ClipboardAction({
emitter: emitter,
emitter,
target: document.querySelector('#input')
});
});
@@ -156,7 +163,7 @@ describe('ClipboardAction', () => {
});
let clip = new ClipboardAction({
emitter: emitter,
emitter,
target: document.querySelector('#input')
});
});
@@ -166,6 +173,7 @@ 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')
});
@@ -184,6 +192,7 @@ 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')
});
@@ -203,6 +212,7 @@ 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')
});
@@ -220,6 +230,7 @@ describe('ClipboardAction', () => {
it('should destroy an existing fake element', () => {
let clip = new ClipboardAction({
emitter: new Emitter(),
container: document.body,
text: 'blah'
});

View File

@@ -26,7 +26,7 @@ describe('Clipboard', () => {
describe('#resolveOptions', () => {
before(() => {
global.fn = function() {};
global.fn = () => {};
});
it('should set action as a function', () => {
@@ -52,6 +52,20 @@ 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', () => {
@@ -79,8 +93,8 @@ describe('Clipboard', () => {
it('should throw an exception when target is invalid', done => {
try {
var clipboard = new Clipboard('.btn', {
target: function() {
const clipboard = new Clipboard('.btn', {
target() {
return null;
}
});