Compare commits

..

8 Commits

Author SHA1 Message Date
Zeno Rocha
b5bc00f2e4 Release v1.3.0 2015-09-29 10:17:15 -07:00
Zeno Rocha
ffb2b3fcd9 Merge pull request #16 from mauriciosoares/feature/umd-support
Adds UMD support
2015-09-29 10:14:23 -07:00
Zeno Rocha
a4a68d8774 Merge pull request #14 from yannickoo/patch-2
Fix anchor links to demo
2015-09-29 08:01:32 -07:00
Mauricio Soares
05a807e2fb Adds UMD support
Using the --standalone option from browserify it automatically wrap your code into a UMD module.
2015-09-29 11:09:28 -03:00
Yannick
0102dd6453 fixes anchor links in readme file 2015-09-29 10:23:37 +02:00
Zeno Rocha
84d1949718 Merge pull request #11 from SpazzMarticus/master
Added unminified dist/clipboard.js
2015-09-29 00:00:18 -07:00
SpazzMarticus
fe6c408e48 Built dist/clipboard.js via npm run publish 2015-09-29 08:45:29 +02:00
SpazzMarticus
1d74794565 Publish-script builds dist/clipboard.js and minifies it to dist/clipboard.min.js 2015-09-29 08:43:23 +02:00
6 changed files with 549 additions and 10 deletions

View File

@@ -56,7 +56,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. The value you include on this attribute needs to match another's element selector.
<a href="http://zenorocha.github.io/clipboard.js/#demo-target"><img width="473" alt="example-2" src="https://cloud.githubusercontent.com/assets/398893/9983467/a4946aaa-5fb1-11e5-9780-f09fcd7ca6c8.png"></a> <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>
```html ```html
<!-- Target --> <!-- Target -->
@@ -74,7 +74,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. If you omit this attribute, `copy` will be used by default.
<a href="http://zenorocha.github.io/clipboard.js/#demo-action"><img width="473" alt="example-3" src="https://cloud.githubusercontent.com/assets/398893/10000358/7df57b9c-6050-11e5-9cd1-fbc51d2fd0a7.png"></a> <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>
```html ```html
<!-- Target --> <!-- Target -->
@@ -92,7 +92,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. 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/#demo-text"><img width="147" alt="example-1" src="https://cloud.githubusercontent.com/assets/398893/10000347/6e16cf8c-6050-11e5-9883-1c5681f9ec45.png"></a> <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>
```html ```html
<!-- Trigger --> <!-- Trigger -->

View File

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

541
dist/clipboard.js vendored Normal file
View File

@@ -0,0 +1,541 @@
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Clipboard = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/**
* Module dependencies.
*/
var closest = require('closest')
, event = require('component-event');
/**
* Delegate event `type` to `selector`
* and invoke `fn(e)`. A callback function
* is returned which may be passed to `.unbind()`.
*
* @param {Element} el
* @param {String} selector
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @return {Function}
* @api public
*/
// Some events don't bubble, so we want to bind to the capture phase instead
// when delegating.
var forceCaptureEvents = ['focus', 'blur'];
exports.bind = function(el, selector, type, fn, capture){
if (forceCaptureEvents.indexOf(type) !== -1) capture = true;
return event.bind(el, type, function(e){
var target = e.target || e.srcElement;
e.delegateTarget = closest(target, selector, true, el);
if (e.delegateTarget) fn.call(el, e);
}, capture);
};
/**
* Unbind event `type`'s callback `fn`.
*
* @param {Element} el
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @api public
*/
exports.unbind = function(el, type, fn, capture){
if (forceCaptureEvents.indexOf(type) !== -1) capture = true;
event.unbind(el, type, fn, capture);
};
},{"closest":2,"component-event":4}],2:[function(require,module,exports){
var matches = require('matches-selector')
module.exports = function (element, selector, checkYoSelf) {
var parent = checkYoSelf ? element : element.parentNode
while (parent && parent !== document) {
if (matches(parent, selector)) return parent;
parent = parent.parentNode
}
}
},{"matches-selector":3}],3:[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;
}
},{}],4:[function(require,module,exports){
var bind = window.addEventListener ? 'addEventListener' : 'attachEvent',
unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent',
prefix = bind !== 'addEventListener' ? 'on' : '';
/**
* Bind `el` event `type` to `fn`.
*
* @param {Element} el
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @return {Function}
* @api public
*/
exports.bind = function(el, type, fn, capture){
el[bind](prefix + type, fn, capture || false);
return fn;
};
/**
* Unbind `el` event `type`'s callback `fn`.
*
* @param {Element} el
* @param {String} type
* @param {Function} fn
* @param {Boolean} capture
* @return {Function}
* @api public
*/
exports.unbind = function(el, type, fn, capture){
el[unbind](prefix + type, fn, capture || false);
return fn;
};
},{}],5:[function(require,module,exports){
function E () {
// Keep this empty so it's easier to inherit from
// (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
}
E.prototype = {
on: function (name, callback, ctx) {
var e = this.e || (this.e = {});
(e[name] || (e[name] = [])).push({
fn: callback,
ctx: ctx
});
return this;
},
once: function (name, callback, ctx) {
var self = this;
var fn = function () {
self.off(name, fn);
callback.apply(ctx, arguments);
};
return this.on(name, fn, ctx);
},
emit: function (name) {
var data = [].slice.call(arguments, 1);
var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
var i = 0;
var len = evtArr.length;
for (i; i < len; i++) {
evtArr[i].fn.apply(evtArr[i].ctx, data);
}
return this;
},
off: function (name, callback) {
var e = this.e || (this.e = {});
var evts = e[name];
var liveEvents = [];
if (evts && callback) {
for (var i = 0, len = evts.length; i < len; i++) {
if (evts[i].fn !== callback) liveEvents.push(evts[i]);
}
}
// Remove event from queue to prevent memory leak
// Suggested by https://github.com/lazd
// Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
(liveEvents.length)
? e[name] = liveEvents
: delete e[name];
return this;
}
};
module.exports = E;
},{}],6:[function(require,module,exports){
/**
* Inner class which performs selection and copy operations.
*/
'use strict';
exports.__esModule = true;
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
var ClipboardAction = (function () {
/**
* Initializes selection from either `text` or `target` property.
* @param {Object} options
*/
function ClipboardAction(options) {
_classCallCheck(this, ClipboardAction);
this.action = options.action;
this.emitter = options.emitter;
this.target = options.target;
this.text = options.text;
this.trigger = options.trigger;
this.selectedText = '';
if (this.text && this.target) {
throw new Error('Multiple attributes declared, use either "target" or "text"');
} else if (this.text) {
this.selectFake();
} else if (this.target) {
this.selectTarget();
} else {
throw new Error('Missing required attributes, use either "target" or "text"');
}
}
/**
* Creates a fake input element, sets its value from `text` property,
* and makes a selection on it.
*/
ClipboardAction.prototype.selectFake = function selectFake() {
var _this = this;
this.removeFake();
this.fakeHandler = document.body.addEventListener('click', function () {
return _this.removeFake();
});
this.fakeElem = document.createElement('input');
this.fakeElem.style.position = 'absolute';
this.fakeElem.style.left = '-9999px';
this.fakeElem.setAttribute('readonly', '');
this.fakeElem.value = this.text;
this.selectedText = this.text;
document.body.appendChild(this.fakeElem);
this.fakeElem.select();
this.copyText();
};
/**
* Only removes the fake element after another click event, that way
* an user can hit `Ctrl+C` to copy because selection still exists.
*/
ClipboardAction.prototype.removeFake = function removeFake() {
if (this.fakeHandler) {
document.body.removeEventListener('click');
this.fakeHandler = null;
}
if (this.fakeElem) {
document.body.removeChild(this.fakeElem);
this.fakeElem = null;
}
};
/**
* Selects the content from element passed on `target` property.
*/
ClipboardAction.prototype.selectTarget = function selectTarget() {
if (this.target.nodeName === 'INPUT' || this.target.nodeName === 'TEXTAREA') {
this.target.select();
this.selectedText = this.target.value;
} else {
var range = document.createRange();
var selection = window.getSelection();
range.selectNodeContents(this.target);
selection.addRange(range);
this.selectedText = selection.toString();
}
this.copyText();
};
/**
* Executes the copy operation based on the current selection.
*/
ClipboardAction.prototype.copyText = function copyText() {
var succeeded = undefined;
try {
succeeded = document.execCommand(this.action);
} catch (err) {
succeeded = false;
}
this.handleResult(succeeded);
};
/**
* Fires an event based on the copy operation result.
* @param {Boolean} succeeded
*/
ClipboardAction.prototype.handleResult = function handleResult(succeeded) {
if (succeeded) {
this.emitter.emit('success', {
action: this.action,
text: this.selectedText,
trigger: this.trigger,
clearSelection: this.clearSelection.bind(this)
});
} else {
this.emitter.emit('error', {
action: this.action,
trigger: this.trigger,
clearSelection: this.clearSelection.bind(this)
});
}
};
/**
* Removes current selection and focus from `target` element.
*/
ClipboardAction.prototype.clearSelection = function clearSelection() {
if (this.target) {
this.target.blur();
}
window.getSelection().removeAllRanges();
};
/**
* Sets the `action` to be performed which can be either 'copy' or 'cut'.
* @param {String} action
*/
_createClass(ClipboardAction, [{
key: 'action',
set: function set(action) {
this._action = action || 'copy';
if (this._action !== 'copy' && this._action !== 'cut') {
throw new Error('Invalid "action" value, use either "copy" or "cut"');
}
},
/**
* Gets the `action` property.
* @return {String}
*/
get: function get() {
return this._action;
}
/**
* Sets the `target` property using an element that will be have its content
* copied.
* @param {Element} target
*/
}, {
key: 'target',
set: function set(target) {
if (target !== undefined) {
if (target && typeof target === 'object' && target.nodeType === 1) {
this._target = target;
} else {
throw new Error('Invalid "target" value, use a valid Element');
}
}
},
/**
* Gets the `target` property.
* @return {String|HTMLElement}
*/
get: function get() {
return this._target;
}
}]);
return ClipboardAction;
})();
exports['default'] = ClipboardAction;
module.exports = exports['default'];
},{}],7:[function(require,module,exports){
'use strict';
exports.__esModule = true;
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
var _clipboardAction = require('./clipboard-action');
var _clipboardAction2 = _interopRequireDefault(_clipboardAction);
var _delegateEvents = require('delegate-events');
var _delegateEvents2 = _interopRequireDefault(_delegateEvents);
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.
*/
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);
});
}
/**
* Defines if attributes would be resolved using an internal setter function
* or a custom function that was passed in the constructor.
* @param {Object} options
*/
Clipboard.prototype.resolveOptions = function resolveOptions(options) {
options = 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
*/
Clipboard.prototype.setAction = function setAction(trigger) {
return trigger.getAttribute(prefix + 'action');
};
/**
* 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');
};
/**
* Defines a new `ClipboardAction` on each click event.
* @param {Event} e
*/
Clipboard.prototype.initialize = function initialize(e) {
if (this.clipboardAction) {
this.clipboardAction = null;
}
this.clipboardAction = new _clipboardAction2['default']({
action: this.action(e.delegateTarget),
target: this.target(e.delegateTarget),
text: this.text(e.delegateTarget),
trigger: e.delegateTarget,
emitter: this
});
};
return Clipboard;
})(_tinyEmitter2['default']);
exports['default'] = Clipboard;
module.exports = exports['default'];
},{"./clipboard-action":6,"delegate-events":1,"tiny-emitter":5}]},{},[7])(7)
});

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
{ {
"name": "clipboard", "name": "clipboard",
"version": "1.2.0", "version": "1.3.0",
"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",
"main": "src/clipboard.js", "main": "src/clipboard.js",
@@ -28,8 +28,8 @@
}, },
"scripts": { "scripts": {
"publish": "npm run build && npm run minify", "publish": "npm run build && npm run minify",
"build": "browserify src/clipboard.js -t [babelify --loose all] -o dist/clipboard.min.js", "build": "browserify src/clipboard.js -s Clipboard -t [babelify --loose all] -o dist/clipboard.js",
"minify": "uglify -s dist/clipboard.min.js -o dist/clipboard.min.js", "minify": "uglify -s dist/clipboard.js -o dist/clipboard.min.js",
"test": "karma start --single-run" "test": "karma start --single-run"
} }
} }

View File

@@ -83,5 +83,3 @@ class Clipboard extends Emitter {
} }
export default Clipboard; export default Clipboard;
global.Clipboard = Clipboard;