This ieCompatibility
branch contains a modified version of the v2.0.2 codebase for ZeroClipboard. It is primarily intended to support IE in compatibility view, with additional features. Please see ZeroClipboard
for the original.
The ClipAndFile library provides an easy way to copy text to the clipboard or save a file using an invisible Adobe Flash movie and a JavaScript interface. The the user interface is left entirely up to you.
This is achieved by automatically floating the invisible movie on top of a DOM element of your choice. Standard mouse events are even propagated out to your DOM element, so you can still have rollover and mousedown effects.
Note that, due to browser and Flash security restrictions, this clipboard injection can ONLY occur when the user clicks on the invisible Flash movie. A simulated click
event from JavaScript will not suffice as this would enable clipboard poisoning.
To use the library, simply include the following JavaScript file in your page:
<script type="text/javascript" src="ClipAndFile.js"></script>
You also need to have the "ClipAndFile.swf
" file available to the browser. If this file is located in the same
directory as your web page, then it will work out of the box. However, if the SWF file is hosted elsewhere, you need
to set the URL like this (place this code after the script tag):
ClipAndFile.config( { swfPath: 'http://YOURSERVER/path/ClipAndFile.swf' } );
Now you are ready to create one or more clients. A client is a single instance of the clipboard library on the page, linked to one or more DOM elements. Here is how to create a client instance:
var client = new ClipAndFile();
You can also include an element or array of elements in the new client. **This example uses jQuery to find "copy buttons".
var client = new ClipAndFile($(".copy-button"));
For the full API documentation, see api/ClipAndFile.md. The full set of Configuration Options are also documented there.
For developers who want to wrap ClipAndFile into a 3rd party plugin (e.g. JamesMGreene/jquery.clipandfile), see the api/ClipAndFile.Core.md documentation instead.
Setting the clipboard text can be done in 4 ways:
-
Add a
copy
event handler in which you callevent.clipboardData.setData
to set the appropriate data. This event is triggered every time ClipAndFile tries to act. Example:client.on( "copy", function (event) { var clipboard = event.clipboardData; clipboard.setData( "text/plain", "Copy me!" ); clipboard.setData( "text/html", "<b>Copy me!</b>" ); clipboard.setData( "application/rtf", "{\\rtf1\\ansi\n{\\b Copy me!}}" ); });
-
Set the "text/plain" [and usually "text/html"] clipboard segments via
data-clipboard-target
attribute on the button. ClipAndFile will look for the target element via ID and try to get the HTML value via.value
,.outerHTML
, or.innerHTML
, and the text value via.value
,.textContent
, or.innerText
. If the HTML and text values for the targeted element match, the value will only be placed into the "text/plain" segment of the clipboard (i.e. the "text/html" segment will cleared).
<button id="my-button_text" data-clipboard-target="clipboard_text">Copy to Clipboard</button>
<button id="my-button_textarea" data-clipboard-target="clipboard_textarea">Copy to Clipboard</button>
<button id="my-button_pre" data-clipboard-target="clipboard_pre">Copy to Clipboard</button>
<input type="text" id="clipboard_text" value="Clipboard Text"/>
<textarea id="clipboard_textarea">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea>
<pre id="clipboard_pre">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</pre>
- Set the "text/plain" clipboard segment via
data-clipboard-text
attribute on the button. Doing this will let ClipAndFile take care of the rest.
<button id="my-button" data-clipboard-text="Copy me!">Copy to Clipboard</button>
- Set the data via the
ClipAndFile.setData
(any segment) method. You can call this function at any time: when the page first loads, or later like in acopy
event handler. Example:
ClipAndFile.setData( "text/plain", "Copy me!" );
The important caveat of using ClipAndFile.setData
is that the data it sets is transient and will only be used for a single copy operation. As such, we do not particularly
recommend using ClipAndFile.setData
(and friends) other than inside of a copy
event handler; however, the API will not prevent you from using it in other ways.
- Set the data via the
client.setText
("text/plain" segment),client.setHtml
("text/html" segment),client.setRichText
("application/rtf" segment), orclient.setData
(any segment) methods. You can call this function at any time: when the page first loads, or later like in acopy
event handler. Example:
client.setText( "Copy me!" );
The important caveat of using client.setData
(and friends) is that the data it sets is transient and will only be used for a single copy operation. As such, we do not particularly
recommend using client.setData
(and friends) other than inside of a copy
event handler; however, the API will not prevent you from using it in other ways.
Saving a file can be done in 4 ways:
-
Add a
copy
event handler in which you callevent.clipboardData.setFile
to set the appropriate data for file save. This event is triggered every time ClipAndFile tries to act. Example:client.on( "copy", function (event) { var clipboard = event.clipboardData; clipboard.setFile( "example.txt", "Save me!", false); });
-
Set the "text/plain" file data via
data-clipboard-target
attribute on the button, along with thedata-clipboard-file
attribute. ClipAndFile will look for the target element via ID and try to get the text value via.value
,.textContent
, or.innerText
, then save to a file of the specified name.
<button id="my-button_text" data-clipboard-target="clipboard_text" data-clipboard-file="text.txt">Copy to Clipboard</button>
<button id="my-button_textarea" data-clipboard-target="clipboard_textarea" data-clipboard-file="textarea.txt">Copy to Clipboard</button>
<button id="my-button_pre" data-clipboard-target="clipboard_pre" data-clipboard-file="pre.txt">Copy to Clipboard</button>
<input type="text" id="clipboard_text" value="Clipboard Text"/>
<textarea id="clipboard_textarea">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea>
<pre id="clipboard_pre">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</pre>
- Set the file data via
data-clipboard-b64
ordata-clipboard-text
attributes on the button, along with thedata-clipboard-file
attribute. ClipAndFile will save the data to the specified file.
<button id="my-button" data-clipboard-text="Copy me!" data-clipboard-file="example.txt">Copy to Clipboard</button>
- Set the data via the
ClipAndFile.setFile
(any segment) method. You can call this function at any time: when the page first loads, or later like in acopy
event handler. Example:
ClipAndFile.setFile( "example.txt", "Save me!", false);
The important caveat of using ClipAndFile.setFile
is that the data it sets is transient and will only be used for a single save operation. As such, we do not particularly
recommend using ClipAndFile.setFile
(and friends) other than inside of a copy
event handler; however, the API will not prevent you from using it in other ways.
Clipping refers to the process of "linking" the Flash movie to a DOM element on the page. Since the Flash movie is completely transparent, the user sees nothing out of the ordinary.
The Flash movie receives the click event and copies the text to the clipboard. Also, mouse actions like hovering and mousedown
generate events that you can capture (see Event Handlers below).
To clip elements, you must pass an element, or array of elements to the clip
function.
Here is how to clip your client library instance to a DOM element:
client.clip( document.getElementById("d_clip_button") );
You can pass in a reference to the actual DOM element object itself or an array of DOM objects. The rest all happens automatically: the movie is created, all your options set, and it is floated above the element, awaiting clicks from the user.
<button id="my-button" data-clipboard-text="Copy me!" title="Click to copy to clipboard.">Copy to Clipboard</button>
And the code:
var client = new ClipAndFile( $("button#my-button") );
Since the Flash movie is floating on top of your DOM element, it will receive all the mouse events before the browser has a chance to catch them. However, for convenience, these events are passed through to your clipboard client which you can capture (see Event Handlers below), so long as the bubbleEvents
configuration property remains set to true
.
In addition to this, ClipAndFile can also manage CSS classes on the clipped elements that mimic the CSS pseudo-classes ":hover" and ":active" on your DOM element. This essentially allows your elements to behave normally, even though the floating Flash movie is the first object receiving all the mouse events during the event bubbling phase. These "pseudo-pseudo-class" names are configurable via the hoverClass
and activeClass
configuration properties.
Example CSS, targeting a DOM element with a class of "clip_button":
.clip_button {
width: 150px;
text-align: center;
border: 1px solid black;
background-color: #ccc;
margin: 10px;
padding: 10px;
}
.clip_button.clipandfile-is-hover { background-color: #eee; }
.clip_button.clipandfile-is-active { background-color: #aaa; }
The following are complete, working examples of using the clipboard client library in HTML pages.
Here is a quick example using as few calls as possible:
<html>
<body>
<div id="d_clip_button" class="clip_button" data-clipboard-text="Copy Me!" title="Click to copy." style="border:1px solid black; padding:20px;">Copy To Clipboard</div>
<script type="text/javascript" src="ClipAndFile.js"></script>
<script type="text/javascript">
var client = new ClipAndFile( document.getElementById('d_clip_button') );
</script>
</body>
</html>
When clicked, the text "Copy me!" will be copied to the clipboard.
Here is a more complete example which exercises many of the configuration options and event handlers:
<html>
<head>
<style type="text/css">
.clip_button {
text-align: center;
border: 1px solid black;
background-color: #ccc;
margin: 10px;
padding: 10px;
}
.clip_button.clipandfile-is-hover { background-color: #eee; }
.clip_button.clipandfile-is-active { background-color: #aaa; }
</style>
</head>
<body>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="ClipAndFile.js"></script>
<div class="clip_button">Copy To Clipboard</div>
<div class="clip_button">Copy This Too!</div>
<script type="text/javascript">
var client = new ClipAndFile( $('.clip_button') );
client.on( 'ready', function(event) {
// console.log( 'movie is loaded' );
client.on( 'copy', function(event) {
event.clipboardData.setData('text/plain', event.target.innerHTML);
} );
client.on( 'aftercopy', function(event) {
console.log('Copied text to clipboard: ' + event.data['text/plain']);
} );
} );
client.on( 'error', function(event) {
// console.log( 'ClipAndFile error of type "' + event.name + '": ' + event.message );
ClipAndFile.destroy();
} );
</script>
</body>
</html>
ClipAndFile creates DOM elements with pre-configured attributes, e.g. a div
element with an ID of "global-clipandfile-html-bridge"
to encapsulate the Flash object.
If you have a need to change the default values, they can be configured by passing in values for containerId
, containerClass
, and/or swfObjectId
using the ClipAndFile.config
method. Configuration of these values is completely optional. These values cannot be reconfigured while the ClipAndFile SWF is actively embedded, and so are completely ignored during that time.
Values for containerId
and swfObjectId
are validated against the HTML4 spec for ID
and Name
tokens.
If using AMD with a library such as RequireJS, etc., you shouldn't need to do any special configuration for ClipAndFile to work correctly as an AMD module.
If using CommonJS with a library such as Browserify, Webmake, etc., you shouldn't need to do any special configuration for ClipAndFile to work correctly as an CommonJS module.
- Cause: Bootstrap's Modal has an
enforceFocus
function that tries to keep the focus on the modal. However, since the ClipAndFile container is an immediate child of thebody
, this enforcement conflicts. Note that this workaround actually overrides a core Bootstrap Modal function, and as such must be kept in sync as this function changes in future versions of Bootstrap. - Workaround: Targeted against Bootstrap v3.x.
if (/MSIE|Trident/.test(window.navigator.userAgent)) {
(function($) {
var zcClass = ClipAndFile.config('containerClass');
var proto = $.fn.modal.Constructor.prototype;
proto.enforceFocus = function() {
$(document)
.off('focusin.bs.modal') /* Guard against infinite focus loop */
.on('focusin.bs.modal', $.proxy(function(e) {
if (this.$element[0] !== e.target &&
!this.$element.has(e.target).length &&
/* Adding this final condition check is the only real change */
!$(e.target).closest(zcClass).length
) {
this.$element.focus();
}
}, this));
};
})(window.jQuery);
}
- Cause: jQuery UI's Dialog (with
{ modal: true }
set) has a_keepFocus
function that tries to keep the focus on the modal. However, since the ClipAndFile container is an immediate child of thebody
, this enforcement conflicts. Luckily, jQuery UI offers more natural extension points than Bootstrap, so the workaround is smaller and less likely to be broken in future versions. - Workaround: Targeted against jQuery UI v1.10.x.
if (/MSIE|Trident/.test(window.navigator.userAgent)) {
(function($) {
var zcClass = ClipAndFile.config('containerClass');
$.widget( 'ui.dialog', $.ui.dialog, {
_allowInteraction: function( event ) {
return this._super(event) || $( event.target ).closest( zcClass ).length;
}
} );
})(window.jQuery);
}
This library is fully compatible with Flash Player 11.0.0 and above, which requires that the clipboard copy operation be initiated by a user click event inside the Flash movie. This is achieved by automatically floating the invisible movie on top of a DOM element of your choice. Standard mouse events are even propagated out to your DOM element, so you can still have rollover and mousedown effects.
Definitely works in IE8+ and all of the evergreen browsers.
Should also work in IE7 if you provide a polyfill for the global JSON
object, e.g.
JSON 2 or
JSON 3.
Because ClipAndFile will be interacting with your users' system clipboards, there are some special considerations specific to the users' operating systems that you should be aware of. With this information, you can make informed decisions of how your site should handle each of these situations.
-
Windows:
- If you want to ensure that your Windows users will be able to paste their copied text into Windows
Notepad and have it honor line breaks, you'll need to ensure that the text uses the sequence
\r\n
instead of just\n
for line breaks. If the text to copy is based on user input (e.g. atextarea
), then you can achieve this transformation by utilizing thecopy
event handler, e.g.
client.on('copy', function(event) { var text = document.getElementById('yourTextArea').value; var windowsText = text.replace(/\n/g, '\r\n'); event.clipboardData.setData('text/plain', windowsText); });
- If you want to ensure that your Windows users will be able to paste their copied text into Windows
Notepad and have it honor line breaks, you'll need to ensure that the text uses the sequence