mirror of
https://github.com/zenorocha/clipboard.js.git
synced 2023-08-10 21:12:48 +03:00
Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b3ad81570e | ||
|
|
17aedf5221 | ||
|
|
e14d92e2f4 | ||
|
|
b7b2259dfb | ||
|
|
c5b416b108 | ||
|
|
019b021624 | ||
|
|
8e56ee61c4 | ||
|
|
83a8effff9 | ||
|
|
e5a6797c82 | ||
|
|
8dc4e2e132 | ||
|
|
0c24503214 | ||
|
|
cc9d562580 | ||
|
|
8fa31029ac | ||
|
|
c16137511c | ||
|
|
15a66df290 | ||
|
|
ff4755fe4c | ||
|
|
0b9a0402b9 | ||
|
|
b3fcd15a8e | ||
|
|
d28418675b | ||
|
|
fab7b16bb8 | ||
|
|
e4de506885 | ||
|
|
3bdb55900d | ||
|
|
71705c6431 | ||
|
|
c666150278 | ||
|
|
cead303e53 | ||
|
|
b0d54c46fe | ||
|
|
5c8af54b8a | ||
|
|
a4c8bc5bf0 | ||
|
|
5147086c48 | ||
|
|
99899441c8 | ||
|
|
51309716cd | ||
|
|
c70a91a67e | ||
|
|
14c5962816 | ||
|
|
29d5127362 | ||
|
|
02c44d4a17 | ||
|
|
4d1fa1ba75 | ||
|
|
0abb217253 | ||
|
|
0085cbc49b | ||
|
|
e4f3fb226c | ||
|
|
c3738cd899 | ||
|
|
c041e2a8f0 | ||
|
|
1b062f72f5 | ||
|
|
fb3cb46d7c |
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "clipboard",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4.1",
|
||||
"description": "Modern copy to clipboard. No Flash. Just 2kb",
|
||||
"license": "MIT",
|
||||
"main": "src/clipboard.js",
|
||||
"main": "dist/clipboard.js",
|
||||
"keywords": [
|
||||
"clipboard",
|
||||
"copy",
|
||||
|
||||
28
contributing.md
Normal file
28
contributing.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Contributing guide
|
||||
|
||||
Want to contribute to Clipboard.js? Awesome!
|
||||
There are many ways you can contribute, see below.
|
||||
|
||||
## Opening issues
|
||||
|
||||
Open an issue to report bugs or to propose new features.
|
||||
|
||||
- Reporting bugs: describe the bug as clearly as you can, including steps to reproduce, what happened and what you were expecting to happen. Also include browser version, OS and other related software's (npm, Node.js, etc) versions when applicable.
|
||||
|
||||
- Proposing features: explain the proposed feature, what it should do, why it is useful, how users should use it. Give us as much info as possible so it will be easier to discuss, access and implement the proposed feature. When you're unsure about a certain aspect of the feature, feel free to leave it open for others to discuss and find an appropriate solution.
|
||||
|
||||
## Proposing pull requests
|
||||
|
||||
Pull requests are very welcome. Note that if you are going to propose drastic changes, be sure to open an issue for discussion first, to make sure that your PR will be accepted before you spend effort coding it.
|
||||
|
||||
Fork the Clipboard.js repository, clone it locally and create a branch for your proposed bug fix or new feature. Avoid working directly on the master branch.
|
||||
|
||||
Implement your bug fix or feature, write tests to cover it and make sure all tests are passing (run a final `npm test` to make sure everything is correct). Then commit your changes, push your bug fix/feature branch to the origin (your forked repo) and open a pull request to the upstream (the repository you originally forked)'s master branch.
|
||||
|
||||
## Documentation
|
||||
|
||||
Documentation is extremely important and takes a fair deal of time and effort to write and keep updated. Please submit any and all improvements you can make to the repository's docs.
|
||||
|
||||
## Known issues
|
||||
If you're using npm@3 you'll probably face some issues related to peerDependencies.
|
||||
https://github.com/npm/npm/issues/9204
|
||||
96
dist/clipboard.js
vendored
96
dist/clipboard.js
vendored
@@ -265,7 +265,7 @@ var ClipboardAction = (function () {
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a fake input element, sets its value from `text` property,
|
||||
* Creates a fake textarea element, sets its value from `text` property,
|
||||
* and makes a selection on it.
|
||||
*/
|
||||
|
||||
@@ -278,9 +278,10 @@ var ClipboardAction = (function () {
|
||||
return _this.removeFake();
|
||||
});
|
||||
|
||||
this.fakeElem = document.createElement('input');
|
||||
this.fakeElem = document.createElement('textarea');
|
||||
this.fakeElem.style.position = 'absolute';
|
||||
this.fakeElem.style.left = '-9999px';
|
||||
this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
|
||||
this.fakeElem.setAttribute('readonly', '');
|
||||
this.fakeElem.value = this.text;
|
||||
this.selectedText = this.text;
|
||||
@@ -383,6 +384,14 @@ var ClipboardAction = (function () {
|
||||
* @param {String} action
|
||||
*/
|
||||
|
||||
/**
|
||||
* Destroy lifecycle.
|
||||
*/
|
||||
|
||||
ClipboardAction.prototype.destroy = function destroy() {
|
||||
this.removeFake();
|
||||
};
|
||||
|
||||
_createClass(ClipboardAction, [{
|
||||
key: 'action',
|
||||
set: function set() {
|
||||
@@ -458,8 +467,6 @@ var _tinyEmitter = require('tiny-emitter');
|
||||
|
||||
var _tinyEmitter2 = _interopRequireDefault(_tinyEmitter);
|
||||
|
||||
var prefix = 'data-clipboard-';
|
||||
|
||||
/**
|
||||
* Base class which takes a selector, delegates a click event to it,
|
||||
* and instantiates a new `ClipboardAction` on each click.
|
||||
@@ -482,6 +489,12 @@ var Clipboard = (function (_Emitter) {
|
||||
this.delegateClick(selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to retrieve attribute value.
|
||||
* @param {String} suffix
|
||||
* @param {Element} element
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines if attributes would be resolved using internal setter functions
|
||||
* or custom functions that were passed in the constructor.
|
||||
@@ -491,9 +504,9 @@ var Clipboard = (function (_Emitter) {
|
||||
Clipboard.prototype.resolveOptions = function resolveOptions() {
|
||||
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
|
||||
|
||||
this.action = typeof options.action === 'function' ? options.action : this.setAction;
|
||||
this.target = typeof options.target === 'function' ? options.target : this.setTarget;
|
||||
this.text = typeof options.text === 'function' ? options.text : this.setText;
|
||||
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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -504,17 +517,26 @@ var Clipboard = (function (_Emitter) {
|
||||
Clipboard.prototype.delegateClick = function delegateClick(selector) {
|
||||
var _this = this;
|
||||
|
||||
_delegateEvents2['default'].bind(document.body, selector, 'click', function (e) {
|
||||
return _this.initialize(e);
|
||||
this.binding = _delegateEvents2['default'].bind(document.body, selector, 'click', function (e) {
|
||||
return _this.onClick(e);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Undelegates a click event on body.
|
||||
* @param {String} selector
|
||||
*/
|
||||
|
||||
Clipboard.prototype.undelegateClick = function undelegateClick() {
|
||||
_delegateEvents2['default'].unbind(document.body, 'click', this.binding);
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines a new `ClipboardAction` on each click event.
|
||||
* @param {Event} e
|
||||
*/
|
||||
|
||||
Clipboard.prototype.initialize = function initialize(e) {
|
||||
Clipboard.prototype.onClick = function onClick(e) {
|
||||
if (this.clipboardAction) {
|
||||
this.clipboardAction = null;
|
||||
}
|
||||
@@ -529,48 +551,62 @@ var Clipboard = (function (_Emitter) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the `action` lookup function.
|
||||
* Default `action` lookup function.
|
||||
* @param {Element} trigger
|
||||
*/
|
||||
|
||||
Clipboard.prototype.setAction = function setAction(trigger) {
|
||||
if (!trigger.hasAttribute(prefix + 'action')) {
|
||||
return;
|
||||
}
|
||||
|
||||
return trigger.getAttribute(prefix + 'action');
|
||||
Clipboard.prototype.defaultAction = function defaultAction(trigger) {
|
||||
return getAttributeValue('action', trigger);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the `target` lookup function.
|
||||
* Default `target` lookup function.
|
||||
* @param {Element} trigger
|
||||
*/
|
||||
|
||||
Clipboard.prototype.setTarget = function setTarget(trigger) {
|
||||
if (!trigger.hasAttribute(prefix + 'target')) {
|
||||
return;
|
||||
}
|
||||
Clipboard.prototype.defaultTarget = function defaultTarget(trigger) {
|
||||
var selector = getAttributeValue('target', trigger);
|
||||
|
||||
var target = trigger.getAttribute(prefix + 'target');
|
||||
return document.querySelector(target);
|
||||
if (selector) {
|
||||
return document.querySelector(selector);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the `text` lookup function.
|
||||
* Default `text` lookup function.
|
||||
* @param {Element} trigger
|
||||
*/
|
||||
|
||||
Clipboard.prototype.setText = function setText(trigger) {
|
||||
if (!trigger.hasAttribute(prefix + 'text')) {
|
||||
return;
|
||||
}
|
||||
Clipboard.prototype.defaultText = function defaultText(trigger) {
|
||||
return getAttributeValue('text', trigger);
|
||||
};
|
||||
|
||||
return trigger.getAttribute(prefix + 'text');
|
||||
/**
|
||||
* Destroy lifecycle.
|
||||
*/
|
||||
|
||||
Clipboard.prototype.destroy = function destroy() {
|
||||
this.undelegateClick();
|
||||
|
||||
if (this.clipboardAction) {
|
||||
this.clipboardAction.destroy();
|
||||
this.clipboardAction = null;
|
||||
}
|
||||
};
|
||||
|
||||
return Clipboard;
|
||||
})(_tinyEmitter2['default']);
|
||||
|
||||
function getAttributeValue(suffix, element) {
|
||||
var attribute = 'data-clipboard-' + suffix;
|
||||
|
||||
if (!element.hasAttribute(attribute)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return element.getAttribute(attribute);
|
||||
}
|
||||
|
||||
exports['default'] = Clipboard;
|
||||
module.exports = exports['default'];
|
||||
|
||||
|
||||
2
dist/clipboard.min.js
vendored
2
dist/clipboard.min.js
vendored
File diff suppressed because one or more lines are too long
21
package.json
21
package.json
@@ -1,42 +1,49 @@
|
||||
{
|
||||
"name": "clipboard",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4.1",
|
||||
"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" }]
|
||||
[
|
||||
"babelify",
|
||||
{
|
||||
"loose": "all"
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"clipboard",
|
||||
"copy",
|
||||
"cut"
|
||||
],
|
||||
"dependencies": {
|
||||
"babelify": "^6.3.0",
|
||||
"browserify": "^11.2.0",
|
||||
"delegate-events": "^1.1.1",
|
||||
"tiny-emitter": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babelify": "^6.3.0",
|
||||
"browserify": "^11.1.0",
|
||||
"karma": "^0.13.10",
|
||||
"karma-browserify": "^4.3.0",
|
||||
"karma-browserify": "^4.4.0",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-mocha": "^0.2.0",
|
||||
"karma-phantomjs-launcher": "^0.2.1",
|
||||
"karma-sinon": "^1.0.4",
|
||||
"mocha": "^2.3.3",
|
||||
"phantomjs-polyfill": "0.0.1",
|
||||
"uglify": "^0.1.5"
|
||||
"uglify": "^0.1.5",
|
||||
"watchify": "^3.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run build-debug && npm run build-min",
|
||||
"build-debug": "browserify src/clipboard.js -s Clipboard -o dist/clipboard.js",
|
||||
"build-min": "uglify -s dist/clipboard.js -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"
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
|
||||
> Modern copy to clipboard. No Flash. Just 2kb
|
||||
|
||||
<a href="http://zenorocha.github.io/clipboard.js/"><img width="728" src="https://cloud.githubusercontent.com/assets/398893/9983535/5ab0a950-5fb4-11e5-9602-e73c0b661883.jpg" alt="Demo"></a>
|
||||
<a href="https://zenorocha.github.io/clipboard.js/"><img width="728" src="https://cloud.githubusercontent.com/assets/398893/9983535/5ab0a950-5fb4-11e5-9602-e73c0b661883.jpg" alt="Demo"></a>
|
||||
|
||||
## Why
|
||||
|
||||
Copy text to the clipboard shouldn't be hard. It shouldn't require dozens of steps to configure or hundreds of KBs to load. But most of all, it shouldn't depend on Flash or any bloated framework.
|
||||
Copying text to the clipboard shouldn't be hard. It shouldn't require dozens of steps to configure or hundreds of KBs to load. But most of all, it shouldn't depend on Flash or any bloated framework.
|
||||
|
||||
That's why clipboard.js exists.
|
||||
|
||||
@@ -30,12 +30,18 @@ If you're not into package management, just [download a ZIP](https://github.com/
|
||||
|
||||
## Setup
|
||||
|
||||
First, include the script located on the `dist` folder
|
||||
First, include the script located on the `dist` folder.
|
||||
|
||||
```html
|
||||
<script src="dist/clipboard.min.js"></script>
|
||||
```
|
||||
|
||||
Or load it from a CDN.
|
||||
|
||||
```html
|
||||
<script src="https://cdn.rawgit.com/zenorocha/clipboard.js/master/dist/clipboard.min.js"></script>
|
||||
```
|
||||
|
||||
Now, you need to instantiate it using a DOM selector. This selector corresponds to the trigger element(s), for example `<button class="btn">`.
|
||||
|
||||
```js
|
||||
@@ -56,7 +62,7 @@ A pretty common use case is to copy content from another element. You can do tha
|
||||
|
||||
The value you include on this attribute needs to match another's element selector.
|
||||
|
||||
<a href="http://zenorocha.github.io/clipboard.js/#example-target"><img width="473" alt="example-2" src="https://cloud.githubusercontent.com/assets/398893/9983467/a4946aaa-5fb1-11e5-9780-f09fcd7ca6c8.png"></a>
|
||||
<a href="https://zenorocha.github.io/clipboard.js/#example-target"><img width="473" alt="example-2" src="https://cloud.githubusercontent.com/assets/398893/9983467/a4946aaa-5fb1-11e5-9780-f09fcd7ca6c8.png"></a>
|
||||
|
||||
```html
|
||||
<!-- Target -->
|
||||
@@ -74,7 +80,7 @@ Additionally, you can define a `data-clipboard-action` attribute to specify if y
|
||||
|
||||
If you omit this attribute, `copy` will be used by default.
|
||||
|
||||
<a href="http://zenorocha.github.io/clipboard.js/#example-action"><img width="473" alt="example-3" src="https://cloud.githubusercontent.com/assets/398893/10000358/7df57b9c-6050-11e5-9cd1-fbc51d2fd0a7.png"></a>
|
||||
<a href="https://zenorocha.github.io/clipboard.js/#example-action"><img width="473" alt="example-3" src="https://cloud.githubusercontent.com/assets/398893/10000358/7df57b9c-6050-11e5-9cd1-fbc51d2fd0a7.png"></a>
|
||||
|
||||
```html
|
||||
<!-- Target -->
|
||||
@@ -92,7 +98,7 @@ As you may expect, the `cut` action only works on `<input>` or `<textarea>` elem
|
||||
|
||||
Truth is, you don't even need another element to copy its content from. You can just include a `data-clipboard-text` attribute in your trigger element.
|
||||
|
||||
<a href="http://zenorocha.github.io/clipboard.js/#example-text"><img width="147" alt="example-1" src="https://cloud.githubusercontent.com/assets/398893/10000347/6e16cf8c-6050-11e5-9883-1c5681f9ec45.png"></a>
|
||||
<a href="https://zenorocha.github.io/clipboard.js/#example-text"><img width="147" alt="example-1" src="https://cloud.githubusercontent.com/assets/398893/10000347/6e16cf8c-6050-11e5-9883-1c5681f9ec45.png"></a>
|
||||
|
||||
```html
|
||||
<!-- Trigger -->
|
||||
@@ -101,30 +107,6 @@ Truth is, you don't even need another element to copy its content from. You can
|
||||
</button>
|
||||
```
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
If you don't want to modify your HTML, there's a pretty handy imperative API for you to use. All you need to do is declare a function, do your thing, and return a value.
|
||||
|
||||
For instance, if you want to dynamically set a `target`, you'll need to return a Node.
|
||||
|
||||
```js
|
||||
new Clipboard('.btn', {
|
||||
target: function(trigger) {
|
||||
return trigger.nextElementSibling;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
If you want to dynamically set a `text`, you'll return a String.
|
||||
|
||||
```js
|
||||
new Clipboard('.btn', {
|
||||
text: function(trigger) {
|
||||
return trigger.getAttribute('aria-label');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Events
|
||||
|
||||
There are cases where you'd like to show some user feedback or capture what has been selected after a copy/cut operation.
|
||||
@@ -148,13 +130,44 @@ clipboard.on('error', function(e) {
|
||||
});
|
||||
```
|
||||
|
||||
For a live demonstration, open this [site](http://zenorocha.github.io/clipboard.js/) and just your console :)
|
||||
For a live demonstration, open this [site](https://zenorocha.github.io/clipboard.js/) and just your console :)
|
||||
|
||||
## Advanced Options
|
||||
|
||||
If you don't want to modify your HTML, there's a pretty handy imperative API for you to use. All you need to do is declare a function, do your thing, and return a value.
|
||||
|
||||
For instance, if you want to dynamically set a `target`, you'll need to return a Node.
|
||||
|
||||
```js
|
||||
new Clipboard('.btn', {
|
||||
target: function(trigger) {
|
||||
return trigger.nextElementSibling;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
If you want to dynamically set a `text`, you'll return a String.
|
||||
|
||||
```js
|
||||
new Clipboard('.btn', {
|
||||
text: function(trigger) {
|
||||
return trigger.getAttribute('aria-label');
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
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
|
||||
var clipboard = new Clipboard('.btn');
|
||||
clipboard.destroy();
|
||||
```
|
||||
|
||||
## Browser Support
|
||||
|
||||
This library relies on both [Selection](https://developer.mozilla.org/en-US/docs/Web/API/Selection) and [execCommand](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand) APIs. The second one is supported in the following browsers.
|
||||
|
||||
| <img src="http://zenorocha.github.io/clipboard.js/assets/images/chrome.png" width="48px" height="48px" alt="Chrome logo"> | <img src="http://zenorocha.github.io/clipboard.js/assets/images/firefox.png" width="48px" height="48px" alt="Firefox logo"> | <img src="http://zenorocha.github.io/clipboard.js/assets/images/ie.png" width="48px" height="48px" alt="Internet Explorer logo"> | <img src="http://zenorocha.github.io/clipboard.js/assets/images/opera.png" width="48px" height="48px" alt="Opera logo"> | <img src="http://zenorocha.github.io/clipboard.js/assets/images/safari.png" width="48px" height="48px" alt="Safari logo"> |
|
||||
| <img src="https://zenorocha.github.io/clipboard.js/assets/images/chrome.png" width="48px" height="48px" alt="Chrome logo"> | <img src="https://zenorocha.github.io/clipboard.js/assets/images/firefox.png" width="48px" height="48px" alt="Firefox logo"> | <img src="https://zenorocha.github.io/clipboard.js/assets/images/ie.png" width="48px" height="48px" alt="Internet Explorer logo"> | <img src="https://zenorocha.github.io/clipboard.js/assets/images/opera.png" width="48px" height="48px" alt="Opera logo"> | <img src="https://zenorocha.github.io/clipboard.js/assets/images/safari.png" width="48px" height="48px" alt="Safari logo"> |
|
||||
|:---:|:---:|:---:|:---:|:---:|
|
||||
| 42+ ✔ | 41+ ✔ | 9+ ✔ | 29+ ✔ | Nope ✘ |
|
||||
|
||||
@@ -162,7 +175,7 @@ Although copy/cut operations with [execCommand](https://developer.mozilla.org/en
|
||||
|
||||
That means you can show a tooltip saying `Copied!` when `success` event is called and `Press Ctrl+C to copy` when `error` event is called because the text is already selected.
|
||||
|
||||
For a live demonstration, open this [site](http://zenorocha.github.io/clipboard.js/) on Safari.
|
||||
For a live demonstration, open this [site](https://zenorocha.github.io/clipboard.js/) on Safari.
|
||||
|
||||
## License
|
||||
|
||||
@@ -45,7 +45,7 @@ class ClipboardAction {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a fake input element, sets its value from `text` property,
|
||||
* Creates a fake textarea element, sets its value from `text` property,
|
||||
* and makes a selection on it.
|
||||
*/
|
||||
selectFake() {
|
||||
@@ -53,9 +53,10 @@ class ClipboardAction {
|
||||
|
||||
this.fakeHandler = document.body.addEventListener('click', () => this.removeFake());
|
||||
|
||||
this.fakeElem = document.createElement('input');
|
||||
this.fakeElem = document.createElement('textarea');
|
||||
this.fakeElem.style.position = 'absolute';
|
||||
this.fakeElem.style.left = '-9999px';
|
||||
this.fakeElem.style.top = (window.pageYOffset || document.documentElement.scrollTop) + 'px';
|
||||
this.fakeElem.setAttribute('readonly', '');
|
||||
this.fakeElem.value = this.text;
|
||||
this.selectedText = this.text;
|
||||
@@ -194,6 +195,13 @@ class ClipboardAction {
|
||||
get target() {
|
||||
return this._target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy lifecycle.
|
||||
*/
|
||||
destroy() {
|
||||
this.removeFake();
|
||||
}
|
||||
}
|
||||
|
||||
export default ClipboardAction;
|
||||
|
||||
@@ -2,8 +2,6 @@ import ClipboardAction from './clipboard-action';
|
||||
import Delegate from 'delegate-events';
|
||||
import Emitter from 'tiny-emitter';
|
||||
|
||||
const prefix = 'data-clipboard-';
|
||||
|
||||
/**
|
||||
* Base class which takes a selector, delegates a click event to it,
|
||||
* and instantiates a new `ClipboardAction` on each click.
|
||||
@@ -26,9 +24,9 @@ class Clipboard extends Emitter {
|
||||
* @param {Object} options
|
||||
*/
|
||||
resolveOptions(options = {}) {
|
||||
this.action = (typeof options.action === 'function') ? options.action : this.setAction;
|
||||
this.target = (typeof options.target === 'function') ? options.target : this.setTarget;
|
||||
this.text = (typeof options.text === 'function') ? options.text : this.setText;
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,14 +34,22 @@ class Clipboard extends Emitter {
|
||||
* @param {String} selector
|
||||
*/
|
||||
delegateClick(selector) {
|
||||
Delegate.bind(document.body, selector, 'click', (e) => this.initialize(e));
|
||||
this.binding = Delegate.bind(document.body, selector, 'click', (e) => this.onClick(e));
|
||||
}
|
||||
|
||||
/**
|
||||
* Undelegates a click event on body.
|
||||
* @param {String} selector
|
||||
*/
|
||||
undelegateClick() {
|
||||
Delegate.unbind(document.body, 'click', this.binding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a new `ClipboardAction` on each click event.
|
||||
* @param {Event} e
|
||||
*/
|
||||
initialize(e) {
|
||||
onClick(e) {
|
||||
if (this.clipboardAction) {
|
||||
this.clipboardAction = null;
|
||||
}
|
||||
@@ -58,41 +64,60 @@ class Clipboard extends Emitter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the `action` lookup function.
|
||||
* Default `action` lookup function.
|
||||
* @param {Element} trigger
|
||||
*/
|
||||
setAction(trigger) {
|
||||
if (!trigger.hasAttribute(prefix + 'action')) {
|
||||
return;
|
||||
}
|
||||
|
||||
return trigger.getAttribute(prefix + 'action');
|
||||
defaultAction(trigger) {
|
||||
return getAttributeValue('action', trigger);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the `target` lookup function.
|
||||
* Default `target` lookup function.
|
||||
* @param {Element} trigger
|
||||
*/
|
||||
setTarget(trigger) {
|
||||
if (!trigger.hasAttribute(prefix + 'target')) {
|
||||
return;
|
||||
}
|
||||
defaultTarget(trigger) {
|
||||
let selector = getAttributeValue('target', trigger);
|
||||
|
||||
let target = trigger.getAttribute(prefix + 'target');
|
||||
return document.querySelector(target);
|
||||
if (selector) {
|
||||
return document.querySelector(selector);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the `text` lookup function.
|
||||
* Default `text` lookup function.
|
||||
* @param {Element} trigger
|
||||
*/
|
||||
setText(trigger) {
|
||||
if (!trigger.hasAttribute(prefix + 'text')) {
|
||||
return;
|
||||
}
|
||||
defaultText(trigger) {
|
||||
return getAttributeValue('text', trigger);
|
||||
}
|
||||
|
||||
return trigger.getAttribute(prefix + 'text');
|
||||
/**
|
||||
* Destroy lifecycle.
|
||||
*/
|
||||
destroy() {
|
||||
this.undelegateClick();
|
||||
|
||||
if (this.clipboardAction) {
|
||||
this.clipboardAction.destroy();
|
||||
this.clipboardAction = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to retrieve attribute value.
|
||||
* @param {String} suffix
|
||||
* @param {Element} element
|
||||
*/
|
||||
function getAttributeValue(suffix, element) {
|
||||
let attribute = `data-clipboard-${suffix}`;
|
||||
|
||||
if (!element.hasAttribute(attribute)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return element.getAttribute(attribute);
|
||||
}
|
||||
|
||||
export default Clipboard;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import Clipboard from '../src/clipboard-action';
|
||||
import ClipboardAction from '../src/clipboard-action';
|
||||
import Emitter from 'tiny-emitter';
|
||||
|
||||
@@ -145,7 +144,7 @@ describe('ClipboardAction', () => {
|
||||
it('should fire a success event on browsers that support copy command', done => {
|
||||
global.stub.returns(true);
|
||||
|
||||
let emitter = new Emitter()
|
||||
let emitter = new Emitter();
|
||||
|
||||
emitter.on('success', () => {
|
||||
done();
|
||||
@@ -160,7 +159,7 @@ describe('ClipboardAction', () => {
|
||||
it('should fire an error event on browsers that support copy command', done => {
|
||||
global.stub.returns(false);
|
||||
|
||||
let emitter = new Emitter()
|
||||
let emitter = new Emitter();
|
||||
|
||||
emitter.on('error', () => {
|
||||
done();
|
||||
@@ -226,4 +225,18 @@ describe('ClipboardAction', () => {
|
||||
assert.equal(selectedText, '');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#destroy', () => {
|
||||
it('should destroy an existing fake element', () => {
|
||||
let clip = new ClipboardAction({
|
||||
emitter: new Emitter(),
|
||||
text: 'blah'
|
||||
});
|
||||
|
||||
clip.selectFake();
|
||||
clip.destroy();
|
||||
|
||||
assert.equal(clip.fakeElem, null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -59,7 +59,7 @@ describe('Clipboard', () => {
|
||||
|
||||
it('should delegate a click event to the passed selector', () => {
|
||||
let element = document.body;
|
||||
let selector = '.btn'
|
||||
let selector = '.btn';
|
||||
let event = 'click';
|
||||
|
||||
let clipboard = new Clipboard(selector);
|
||||
@@ -69,11 +69,32 @@ describe('Clipboard', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('#initialize', () => {
|
||||
describe('#undelegateClick', function() {
|
||||
before(() => {
|
||||
global.spy = sinon.spy(Delegate, 'unbind');
|
||||
});
|
||||
|
||||
after(() => {
|
||||
global.spy.restore();
|
||||
});
|
||||
|
||||
it('should undelegate a click event', () => {
|
||||
let element = document.body;
|
||||
let event = 'click';
|
||||
|
||||
let clipboard = new Clipboard('.btn');
|
||||
clipboard.undelegateClick();
|
||||
|
||||
assert.ok(global.spy.calledOnce);
|
||||
assert.ok(global.spy.calledWith(element, event));
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onClick', () => {
|
||||
it('should create a new instance of ClipboardAction', () => {
|
||||
let clipboard = new Clipboard('.btn');
|
||||
|
||||
clipboard.initialize(global.event);
|
||||
clipboard.onClick(global.event);
|
||||
assert.instanceOf(clipboard.clipboardAction, ClipboardAction);
|
||||
});
|
||||
|
||||
@@ -84,7 +105,7 @@ describe('Clipboard', () => {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
clipboard.initialize(global.event);
|
||||
clipboard.onClick(global.event);
|
||||
}
|
||||
catch(e) {
|
||||
assert.equal(e.message, 'Invalid "target" value, use a valid Element');
|
||||
@@ -92,4 +113,15 @@ describe('Clipboard', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('#destroy', () => {
|
||||
it('should destroy an existing instance of ClipboardAction', () => {
|
||||
let clipboard = new Clipboard('.btn');
|
||||
|
||||
clipboard.onClick(global.event);
|
||||
clipboard.destroy();
|
||||
|
||||
assert.equal(clipboard.clipboardAction, null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user