Compare commits

...

10 Commits

Author SHA1 Message Date
Zeno Rocha
1539bba290 Release v1.3.1 2015-09-29 22:35:01 -07:00
Zeno Rocha
3c414a6b2e Renames npm scripts #19 2015-09-29 22:33:39 -07:00
Zeno Rocha
aeec3fd520 Source formatting #19 2015-09-29 22:28:15 -07:00
Mauricio Soares
4534fc4ca0 Adds test for browserify
This commit adds tests to make sure that the browserify bundle will work in the dist file of clipboard.js

This commit adds the mocha and chai modules, since karma doesn't work well with node only tests.

Also splited tests tasks in package.json and updated .gitignore
2015-09-29 22:16:32 -07:00
Mauricio Soares
623614a4e0 Adds commonjs support
These configs in package.json enables the dist file to be required in commonjs envs without babel.
2015-09-29 22:16:32 -07:00
Zeno Rocha
a5e29bd420 Removes code from #constructor to separate functions 2015-09-29 22:14:26 -07:00
Zeno Rocha
3394f59691 Returns undefined instead of null if attributes does not exists #21 2015-09-29 18:24:33 -07:00
Jory Graham
d66aab1124 Default options for ClipboardAction too 2015-09-29 20:23:05 -04:00
Jory Graham
902c730a4d Use undefined for default parameters 2015-09-29 20:09:17 -04:00
rspecht
14baab7386 using default parameters instead the 'or' approach 2015-09-29 18:36:07 -03:00
11 changed files with 237 additions and 105 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
npm-debug.log
bower_components
node_modules

View File

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

123
dist/clipboard.js vendored
View File

@@ -207,7 +207,8 @@ module.exports = E;
},{}],6:[function(require,module,exports){
/**
* Inner class which performs selection and copy operations.
* Inner class which performs selection from either `text` or `target`
* properties and then executes copy or cut operations.
*/
'use strict';
@@ -219,13 +220,24 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
var ClipboardAction = (function () {
/**
* Initializes selection from either `text` or `target` property.
* @param {Object} options
*/
function ClipboardAction(options) {
_classCallCheck(this, ClipboardAction);
this.resolveOptions(options);
this.initSelection();
}
/**
* Defines base properties passed from constructor.
* @param {Object} options
*/
ClipboardAction.prototype.resolveOptions = function resolveOptions() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
this.action = options.action;
this.emitter = options.emitter;
this.target = options.target;
@@ -233,7 +245,14 @@ var ClipboardAction = (function () {
this.trigger = options.trigger;
this.selectedText = '';
};
/**
* Decides which selection strategy is going to be applied based
* on the existence of `text` and `target` properties.
*/
ClipboardAction.prototype.initSelection = function initSelection() {
if (this.text && this.target) {
throw new Error('Multiple attributes declared, use either "target" or "text"');
} else if (this.text) {
@@ -243,7 +262,7 @@ var ClipboardAction = (function () {
} else {
throw new Error('Missing required attributes, use either "target" or "text"');
}
}
};
/**
* Creates a fake input element, sets its value from `text` property,
@@ -366,8 +385,10 @@ var ClipboardAction = (function () {
_createClass(ClipboardAction, [{
key: 'action',
set: function set(action) {
this._action = action || 'copy';
set: function set() {
var action = arguments.length <= 0 || arguments[0] === undefined ? 'copy' : arguments[0];
this._action = action;
if (this._action !== 'copy' && this._action !== 'cut') {
throw new Error('Invalid "action" value, use either "copy" or "cut"');
@@ -383,8 +404,8 @@ var ClipboardAction = (function () {
}
/**
* Sets the `target` property using an element that will be have its content
* copied.
* Sets the `target` property using an element
* that will be have its content copied.
* @param {Element} target
*/
}, {
@@ -448,33 +469,27 @@ var Clipboard = (function (_Emitter) {
_inherits(Clipboard, _Emitter);
/**
* Delegates a click event on the passed selector.
* @param {String} selector
* @param {Object} options
*/
function Clipboard(selector, options) {
var _this = this;
_classCallCheck(this, Clipboard);
_Emitter.call(this);
this.resolveOptions(options);
_delegateEvents2['default'].bind(document.body, selector, 'click', function (e) {
return _this.initialize(e);
});
this.delegateClick(selector);
}
/**
* Defines if attributes would be resolved using an internal setter function
* or a custom function that was passed in the constructor.
* Defines if attributes would be resolved using internal setter functions
* or custom functions that were passed in the constructor.
* @param {Object} options
*/
Clipboard.prototype.resolveOptions = function resolveOptions(options) {
options = options || {};
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;
@@ -482,34 +497,16 @@ var Clipboard = (function (_Emitter) {
};
/**
* Sets the `action` lookup function.
* @param {Element} trigger
* Delegates a click event on the passed selector.
* @param {String} selector
*/
Clipboard.prototype.setAction = function setAction(trigger) {
return trigger.getAttribute(prefix + 'action');
};
Clipboard.prototype.delegateClick = function delegateClick(selector) {
var _this = this;
/**
* Sets the `target` lookup function.
* @param {Element} trigger
*/
Clipboard.prototype.setTarget = function setTarget(trigger) {
var target = trigger.getAttribute(prefix + 'target');
if (target) {
return document.querySelector(target);
}
};
/**
* Sets the `text` lookup function.
* @param {Element} trigger
*/
Clipboard.prototype.setText = function setText(trigger) {
return trigger.getAttribute(prefix + 'text');
_delegateEvents2['default'].bind(document.body, selector, 'click', function (e) {
return _this.initialize(e);
});
};
/**
@@ -531,6 +528,46 @@ var Clipboard = (function (_Emitter) {
});
};
/**
* Sets the `action` lookup function.
* @param {Element} trigger
*/
Clipboard.prototype.setAction = function setAction(trigger) {
if (!trigger.hasAttribute(prefix + 'action')) {
return;
}
return trigger.getAttribute(prefix + 'action');
};
/**
* Sets the `target` lookup function.
* @param {Element} trigger
*/
Clipboard.prototype.setTarget = function setTarget(trigger) {
if (!trigger.hasAttribute(prefix + 'target')) {
return;
}
var target = trigger.getAttribute(prefix + 'target');
return document.querySelector(target);
};
/**
* Sets the `text` lookup function.
* @param {Element} trigger
*/
Clipboard.prototype.setText = function setText(trigger) {
if (!trigger.hasAttribute(prefix + 'text')) {
return;
}
return trigger.getAttribute(prefix + 'text');
};
return Clipboard;
})(_tinyEmitter2['default']);

File diff suppressed because one or more lines are too long

View File

@@ -10,6 +10,8 @@ module.exports = function(karma) {
'./node_modules/phantomjs-polyfill/bind-polyfill.js'
],
exclude: ['test/module-systems.js'],
preprocessors: {
'src/**/*.js' : ['browserify'],
'test/**/*.js': ['browserify']

View File

@@ -1,9 +1,15 @@
{
"name": "clipboard",
"version": "1.3.0",
"version": "1.3.1",
"description": "Modern copy to clipboard. No Flash. Just 2kb",
"repository": "zenorocha/clipboard.js",
"main": "src/clipboard.js",
"main": "dist/clipboard.js",
"browser": "src/clipboard.js",
"browserify": {
"transform": [
["babelify", { "loose": "all" }]
]
},
"license": "MIT",
"keywords": [
"clipboard",
@@ -23,13 +29,16 @@
"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"
},
"scripts": {
"publish": "npm run build && npm run minify",
"build": "browserify src/clipboard.js -s Clipboard -t [babelify --loose all] -o dist/clipboard.js",
"minify": "uglify -s dist/clipboard.js -o dist/clipboard.min.js",
"test": "karma start --single-run"
"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",
"test": "npm run test-browser && npm run test-server",
"test-browser": "karma start --single-run",
"test-server": "mocha test/module-systems.js"
}
}

View File

@@ -1,12 +1,21 @@
/**
* Inner class which performs selection and copy operations.
* Inner class which performs selection from either `text` or `target`
* properties and then executes copy or cut operations.
*/
class ClipboardAction {
/**
* Initializes selection from either `text` or `target` property.
* @param {Object} options
*/
constructor(options) {
this.resolveOptions(options);
this.initSelection();
}
/**
* Defines base properties passed from constructor.
* @param {Object} options
*/
resolveOptions(options = {}) {
this.action = options.action;
this.emitter = options.emitter;
this.target = options.target;
@@ -14,7 +23,13 @@ class ClipboardAction {
this.trigger = options.trigger;
this.selectedText = '';
}
/**
* Decides which selection strategy is going to be applied based
* on the existence of `text` and `target` properties.
*/
initSelection() {
if (this.text && this.target) {
throw new Error('Multiple attributes declared, use either "target" or "text"');
}
@@ -140,8 +155,8 @@ class ClipboardAction {
* Sets the `action` to be performed which can be either 'copy' or 'cut'.
* @param {String} action
*/
set action(action) {
this._action = action || 'copy';
set action(action = 'copy') {
this._action = action;
if (this._action !== 'copy' && this._action !== 'cut') {
throw new Error('Invalid "action" value, use either "copy" or "cut"');
@@ -157,8 +172,8 @@ class ClipboardAction {
}
/**
* Sets the `target` property using an element that will be have its content
* copied.
* Sets the `target` property using an element
* that will be have its content copied.
* @param {Element} target
*/
set target(target) {

View File

@@ -10,7 +10,6 @@ const prefix = 'data-clipboard-';
*/
class Clipboard extends Emitter {
/**
* Delegates a click event on the passed selector.
* @param {String} selector
* @param {Object} options
*/
@@ -18,49 +17,26 @@ class Clipboard extends Emitter {
super();
this.resolveOptions(options);
Delegate.bind(document.body, selector, 'click', (e) => this.initialize(e));
this.delegateClick(selector);
}
/**
* Defines if attributes would be resolved using an internal setter function
* or a custom function that was passed in the constructor.
* Defines if attributes would be resolved using internal setter functions
* or custom functions that were passed in the constructor.
* @param {Object} options
*/
resolveOptions(options) {
options = 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;
}
/**
* Sets the `action` lookup function.
* @param {Element} trigger
* Delegates a click event on the passed selector.
* @param {String} selector
*/
setAction(trigger) {
return trigger.getAttribute(prefix + 'action');
}
/**
* Sets the `target` lookup function.
* @param {Element} trigger
*/
setTarget(trigger) {
let target = trigger.getAttribute(prefix + 'target');
if (target) {
return document.querySelector(target);
}
}
/**
* Sets the `text` lookup function.
* @param {Element} trigger
*/
setText(trigger) {
return trigger.getAttribute(prefix + 'text');
delegateClick(selector) {
Delegate.bind(document.body, selector, 'click', (e) => this.initialize(e));
}
/**
@@ -80,6 +56,43 @@ class Clipboard extends Emitter {
emitter : this
});
}
/**
* Sets the `action` lookup function.
* @param {Element} trigger
*/
setAction(trigger) {
if (!trigger.hasAttribute(prefix + 'action')) {
return;
}
return trigger.getAttribute(prefix + 'action');
}
/**
* Sets the `target` lookup function.
* @param {Element} trigger
*/
setTarget(trigger) {
if (!trigger.hasAttribute(prefix + 'target')) {
return;
}
let target = trigger.getAttribute(prefix + 'target');
return document.querySelector(target);
}
/**
* Sets the `text` lookup function.
* @param {Element} trigger
*/
setText(trigger) {
if (!trigger.hasAttribute(prefix + 'text')) {
return;
}
return trigger.getAttribute(prefix + 'text');
}
}
export default Clipboard;

View File

@@ -19,7 +19,23 @@ describe('ClipboardAction', () => {
document.body.innerHTML = '';
});
describe('#constructor', () => {
describe('#resolveOptions', () => {
it('should set base properties', () => {
let clip = new ClipboardAction({
emitter: new Emitter(),
text: 'foo'
});
assert.property(clip, 'action');
assert.property(clip, 'emitter');
assert.property(clip, 'target');
assert.property(clip, 'text');
assert.property(clip, 'trigger');
assert.property(clip, 'selectedText');
});
});
describe('#initSelection', () => {
it('should throw an error since both "text" and "target" were passed', done => {
try {
new ClipboardAction({
@@ -35,9 +51,7 @@ describe('ClipboardAction', () => {
it('should throw an error since neither "text" nor "target" were passed', done => {
try {
new ClipboardAction({
action: ''
});
new ClipboardAction();
}
catch(e) {
assert.equal(e.message, 'Missing required attributes, use either "target" or "text"');

View File

@@ -1,5 +1,6 @@
import Clipboard from '../src/clipboard';
import ClipboardAction from '../src/clipboard-action';
import Delegate from 'delegate-events';
describe('Clipboard', () => {
before(() => {
@@ -18,28 +19,53 @@ describe('Clipboard', () => {
});
describe('#resolveOptions', function() {
before(() => {
global.fn = function() {};
});
it('should set action as a function', () => {
var fn = function() {};
var clipboard = new Clipboard('.btn', {
action: fn
let clipboard = new Clipboard('.btn', {
action: global.fn
});
assert.equal(fn, clipboard.action);
assert.equal(global.fn, clipboard.action);
});
it('should set target as a function', () => {
var fn = function() {};
var clipboard = new Clipboard('.btn', {
target: fn
let clipboard = new Clipboard('.btn', {
target: global.fn
});
assert.equal(fn, clipboard.target);
assert.equal(global.fn, clipboard.target);
});
it('should set text as a function', () => {
var fn = function() {};
var clipboard = new Clipboard('.btn', {
text: fn
let clipboard = new Clipboard('.btn', {
text: global.fn
});
assert.equal(fn, clipboard.text);
assert.equal(global.fn, clipboard.text);
});
});
describe('#delegateClick', function() {
before(() => {
global.spy = sinon.spy(Delegate, 'bind');
});
after(() => {
global.spy.restore();
});
it('should delegate a click event to the passed selector', () => {
let element = document.body;
let selector = '.btn'
let event = 'click';
let clipboard = new Clipboard(selector);
assert.ok(global.spy.calledOnce);
assert.ok(global.spy.calledWith(element, selector, event));
});
});

15
test/module-systems.js Normal file
View File

@@ -0,0 +1,15 @@
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
});