This documents details the ClipAndFile API, including various types of properties, methods, and events.
[String
] The version of the ClipAndFile library being used, e.g. "v1.0.0"
.
var config = ClipAndFile.config();
[Object
] Get a copy of the active configuration for ClipAndFile.
var swfPath = ClipAndFile.config("swfPath");
[*
] Get a copy of the actively configured value for this configuration property for ClipAndFile.
var config = ClipAndFile.config({
forceHandCursor: true
});
[Object
] Set the active configuration for ClipAndFile. Returns a copy of the updated active configuration. For complete details about what can be configured, see Configuration Options below.
[undefined
] Create the Flash bridge SWF object. IMPORTANT: This method should be considered private.
[undefined
] Emit the "destroy"
event, remove all event handlers, and destroy the Flash bridge.
ClipAndFile.setData("text/plain", "Blah");
[undefined
] Set the pending data
of type format
for clipboard injection.
ClipAndFile.setData({
"text/plain": "Blah",
"text/html": "<b>Blah</b>"
});
[undefined
] Set the pending data
of various formats for clipboard injection.
ClipAndFile.setFile("example.txt", "Blah", false);
[undefined
] Set the pending filename
with data
and true if b64
format for file save.
ClipAndFile.clearData("text/plain");
[undefined
] Clear the pending data of type format
for clipboard injection.
ClipAndFile.clearData();
[undefined
] Clear the pending data of ALL formats for clipboard injection and file save.
ClipAndFile.activate(document.getElementById("d_clip_button"));
[undefined
] "Activate" the provided element by moving the Flash SWF object in front of it.
[undefined
] "Deactivate" the currently "activated" element, moving the Flash SWF object off the screen.
[Object
] Diagnostic method that describes the state of the browser, Flash Player, and ClipAndFile.
[Boolean
] Indicates if Flash Player is definitely unusable (disabled, outdated, unavailable, or deactivated). IMPORTANT: This method should be considered private.
var listenerFn = function(e) { var ClipAndFile = this; /* ... */ };
ClipAndFile.on("ready", listenerFn);
var listenerObj = {
handleEvent: function(e) { var listenerObj = this; /* ... */ }
};
ClipAndFile.on("error", listenerObj);
[undefined
] Add a listener
function/object for an eventType
.
ClipAndFile.on("ready error", function(e) { /* ... */ });
[undefined
] Add a listener
function/object for multiple eventType
s.
ClipAndFile.on({
"ready": function(e) { /* ... */ },
"error": function(e) { /* ... */ }
});
[undefined
] Add a set of eventType
to listener
function/object mappings.
ClipAndFile.off("ready", listenerFn);
ClipAndFile.off("error", listenerObj);
[undefined
] Remove a listener
function/object for an eventType
.
ClipAndFile.off("ready error", listenerFn);
[undefined
] Remove a listener
function/object for multiple eventType
s.
ClipAndFile.off({
"ready": readyListenerFn,
"error": errorListenerFn
});
[undefined
] Remove a set of eventType
to listener
function/object mappings.
ClipAndFile.off("ready");
[undefined
] Remove ALL listener functions/objects for an eventType
.
ClipAndFile.off();
[undefined
] Remove ALL listener functions/objects for ALL registered event types.
ClipAndFile.emit("ready");
ClipAndFile.emit({
type: "error",
name: "flash-disabled"
});
var pendingCopyData = ClipAndFile.emit("copy");
[undefined
, or a Flash-friendly data Object
for the "copy"
event] Dispatch an event to all
registered listeners. The emission of some types of events will result in side effects.
var listeners = ClipAndFile.handlers("ready");
[Array
] Retrieves a copy of the registered listener functions/objects for the given eventType
.
var listeners = ClipAndFile.handlers();
[Object
] Retrieves a copy of the map of registered listener functions/objects for ALL event types.
The ready
event is fired when the Flash SWF completes loading and is ready for action. Please
note that you need to set most configuration options [with ClipAndFile.config(...)
]
before ClipAndFile.create()
is invoked.
ClipAndFile.on("ready", function(e) {
/*
e = {
type: "ready",
message: "Flash communication is established",
target: null,
relatedTarget: null,
currentTarget: flashSwfObjectRef,
version: "11.2.202",
timeStamp: Date.now()
};
*/
});
On click
, the Flash object will fire off a beforecopy
event. This event is generally only
used for "UI prepartion" if you want to alter anything before the copy
event fires.
IMPORTANT: Handlers of this event are expected to operate synchronously if they intend to be finished before the "copy" event is triggered.
ClipAndFile.on("beforecopy", function(e) {
/*
e = {
type: "beforecopy",
target: currentlyActivatedElementOrNull,
relatedTarget: dataClipboardElementTargetOfCurrentlyActivatedElementOrNull,
currentTarget: flashSwfObjectRef,
timeStamp: Date.now()
};
*/
});
On click
(and after the beforecopy
event), the Flash object will fire off a copy
event. If
the HTML object has data-clipboard-text
or data-clipboard-target
, then ClipAndFile will take
care of putting an initial set of data on the clipboard. Alternatively, if you have specified
data-clipboard-file
as well as either data-clipboard-text
, data-clipboard-b64
, or
data-clipboard-target
, then ClipAndFile will take care of saving that data to the given file.
It will then invoke any copy
event handlers, in which you can call event.clipboardData.setData
to set the clipboard data or event.clipboardData.setFile
to set the file, which will complete the loop.
IMPORTANT: If a handler of this event intends to modify the pending data for clipboard
injection, it MUST operate synchronously in order to maintain the temporarily elevated
permissions granted by the user's click
event. The most common "gotcha" for this restriction is
if someone wants to make an asynchronous XMLHttpRequest in response to the copy
event to get the
data to inject — this won't work; make it a synchronous XMLHttpRequest instead, or do the
work in advance before the copy
event is fired.
ClipAndFile.on("copy", function(e) {
/*
e = {
type: "copy",
target: currentlyActivatedElementOrNull,
relatedTarget: dataClipboardElementTargetOfCurrentlyActivatedElementOrNull,
currentTarget: flashSwfObjectRef,
timeStamp: Date.now(),
clipboardData: {
setData: ClipAndFile.setData,
setFile: ClipAndFile.setFile,
clearData: ClipAndFile.clearData
}
};
*/
});
The aftercopy
event is fired when the text is copied [or failed to copy] to the clipboard.
ClipAndFile.on("aftercopy", function(e) {
/*
e = {
type: "aftercopy",
target: currentlyActivatedElementOrNull,
relatedTarget: dataClipboardElementTargetOfCurrentlyActivatedElementOrNull,
currentTarget: flashSwfObjectRef,
timeStamp: Date.now(),
success: {
"text/plain": true,
"text/html": true,
"application/rtf": false
},
data: {
"text/plain": "Blah",
"text/html": "<b>Blah</b>",
"application/rtf": "{\\rtf1\\ansi\n{\\b Blah}}"
}
};
*/
});
The destroy
event is fired when ClipAndFile.destroy()
is invoked.
IMPORTANT: Handlers of this event are expected to operate synchronously if they intend to be finished before the destruction is complete.
ClipAndFile.on("destroy", function(e) {
/*
e = {
type: "destroy",
target: null,
relatedTarget: null,
currentTarget: flashSwfObjectRef,
timeStamp: Date.now(),
success: {
"text/plain": true,
"text/html": true,
"application/rtf": false
},
data: {
"text/plain": "Blah",
"text/html": "<b>Blah</b>",
"application/rtf": "{\\rtf1\\ansi\n{\\b Blah}}"
}
};
*/
});
The error
event is fired under a number of conditions, which will be detailed as sub-sections below.
Some consumers may not consider all error
types to be critical, and thus ClipAndFile does not take it upon
itself to implode by calling ClipAndFile.destroy()
under error conditions. However, many consumers may
want to do just that.
This type of error
event fires when Flash Player is either not installed or not enabled in the browser.
ClipAndFile.on("error", function(e) {
/*
e = {
type: "error",
name: "flash-disabled",
messsage: "Flash is disabled or not installed",
target: null,
relatedTarget: null,
currentTarget: flashSwfObjectRef,
timeStamp: Date.now(),
minimumVersion: "11.0.0"
};
*/
});
This type of error
event fires when Flash Player is installed in the browser but the version is too old
for ClipAndFile. ClipAndFile requires Flash Player 11.0.0 or above.
ClipAndFile.on("error", function(e) {
/*
e = {
type: "error",
name: "flash-outdated",
messsage: "Flash is too outdated to support ClipAndFile",
target: null,
relatedTarget: null,
currentTarget: flashSwfObjectRef,
timeStamp: Date.now(),
minimumVersion: "11.0.0",
version: "10.3.183"
};
*/
});
This type of error
event fires when the browser's installation of Flash Player cannot communicate bidirectionally with JavaScript.
ClipAndFile.on("error", function(e) {
/*
e = {
type: "error",
name: "flash-unavailable",
messsage: "Flash is unable to communicate bidirectionally with JavaScript",
target: null,
relatedTarget: null,
currentTarget: flashSwfObjectRef,
timeStamp: Date.now(),
minimumVersion: "11.0.0",
version: "11.2.202"
};
*/
});
This type of error
event fires when the browser's installation of Flash Player is either too old
for the browser [but not too old for ClipAndFile] or if Flash objects are configured as
click-to-play and the user does not authorize it within _globalConfig.flashLoadTimeout
milliseconds or does not authorize it at all.
ClipAndFile.on("error", function(e) {
/*
e = {
type: "error",
name: "flash-deactivated",
messsage: "Flash is too outdated for your browser and/or is configured as click-to-activate",
target: null,
relatedTarget: null,
currentTarget: flashSwfObjectRef,
timeStamp: Date.now(),
minimumVersion: "11.0.0",
version: "11.2.202"
};
*/
});
This type of error
event fires when the SWF loads successfully but takes longer than
_globalConfig.flashLoadTimeout
milliseconds to do so. This would likely be caused by
one of the following situations:
- Too short of a
_globalConfig.flashLoadTimeout
duration configured - Network latency
- The user's installation of Flash is configured as click-to-play but then authorized by the user too late such that the SWF does not finish loading before the timeout period has expired (or it may have expired before they authorized it at all).
The appropriate response to this event is left up to the consumer. For instance, if they
chose to invoke ClipAndFile.destroy()
in response to the earlier
error[name = "flash-deactivated"]
event but then receive this error[name = "flash-overdue"]
event, they may choose to "restart" their process and construct new ClipAndFile client instances,
or they may choose to just log the error to their server so they can consider increasing the
allowed timeout duration in the future.
This may be especially important for SPA or PJAX-based applications to consider as their users may remain on a single page for an extended period of time during which they possibly could have enjoyed an improved experience if ClipAndFile had been "restarted" after an initial hiccup.
ClipAndFile.on("error", function(e) {
/*
e = {
type: "error",
name: "flash-overdue",
messsage: "Flash communication was established but NOT within the acceptable time limit",
target: null,
relatedTarget: null,
currentTarget: flashSwfObjectRef,
timeStamp: Date.now(),
minimumVersion: "11.0.0",
version: "11.2.202"
};
*/
});
The following properties and methods are accessible via a ClipAndFile
client instance, e.g.
var clippedEl = document.getElementById("d_clip_button");
var client = new ClipAndFile(clippedEl);
[String
] A unique identifier for this ClipAndFile client instance.
[undefined
] Remove all event handlers and unclip all clipped elements.
client.setText("Blah");
[this
] Set the pending data
of type "text/plain"
for clipboard injection.
client.setHtml("<b>Blah</b>");
[this
] Set the pending data
of type "text/html"
for clipboard injection.
client.setRichText("{\\rtf1\\ansi\n{\\b Blah}}");
[this
] Set the pending data
of type "application/rtf"
for clipboard injection.
client.setData("text/plain", "Blah");
[this
] Set the pending data
of type format
for clipboard injection.
client.setData({
"text/plain": "Blah",
"text/html": "<b>Blah</b>"
});
[this
] Set the pending data
of various formats for clipboard injection. This particular
function signature (passing in an Object
) will implicitly clear out any existing pending data.
client.setFile("example.txt", "Blah", false);
[undefined
] Set the pending filename
with data
and true if b64
format for file save.
client.clearData("text/plain");
[this
] Clear the pending data of type format
for clipboard injection.
client.clearData();
[this
] Clear the pending data of ALL formats for clipboard injection.
client.clip(document.getElementById("d_clip_button"))
client.clip(document.querySelectorAll(".clip_button"));
client.clip(jQuery(".clip_button"));
[this
] Register clipboard actions for new element(s) to the client. This includes
automatically invoking ClipAndFile.activate
on the current element when it is hovered over,
unless the autoActivate
configuration property is set to false
.
client.unclip(document.getElementById("d_clip_button"))
client.unclip(document.querySelectorAll(".clip_button"));
client.unclip(jQuery(".clip_button"));
client.unclip();
[this
] Unregister the clipboard actions of previously registered element(s) on the page.
If no elements are provided, ALL clipped/registered elements will be unregistered.
var els = client.elements();
[Array
] Get all of the elements to which this client is clipped/registered.
var listenerFn = function(e) { var client = this; /* ... */ };
client.on("ready", listenerFn);
var listenerObj = {
handleEvent: function(e) { var listenerObj = this; /* ... */ }
};
client.on("error", listenerObj);
[this
] Add a listener
function/object for an eventType
within this client instance.
client.on("ready error", function(e) { /* ... */ });
[this
] Add a listener
function/object for multiple eventType
s within this client instance.
client.on({
"ready": function(e) { /* ... */ },
"error": function(e) { /* ... */ }
});
[this
] Add a set of eventType
to listener
function/object mappings within this client instance.
client.off("ready", listenerFn);
client.off("error", listenerObj);
[this
] Remove a listener
function/object for an eventType
within this client instance.
client.off("ready error", listenerFn);
[this
] Remove a listener
function/object for multiple eventType
s within this client instance.
client.off({
"ready": readyListenerFn,
"error": errorListenerFn
});
[this
] Remove a set of eventType
to listener
function/object mappings within this client instance.
client.off("ready");
[this
] Remove ALL listener functions/objects for an eventType
within this client instance.
client.off();
[this
] Remove ALL listener functions/objects for ALL registered event types within this client instance.
client.emit("ready");
client.emit({
type: "error",
name: "flash-disabled"
});
[undefined
] Dispatch an event to all registered listeners within this client instance.
var listeners = client.handlers("ready");
[Array
] Retrieves a copy of the registered listener functions/objects for the given eventType
within this client instance.
var listeners = client.handlers();
[Object
] Retrieves a copy of the map of registered listener functions/objects for ALL event types within this client instance.
See the Static Events listing. The ClipAndFile client instances regurgitate the ClipAndFile.Core
events, ONLY if the event is NOT impertinent to this particular client. The only difference is that the clients' event dispatching will update the event
object to include a client
property that references the relevant client instance, e.g.:
var client = new ClipAndFile();
client.on("ready", function(e) {
if (e.client === client && client === this) {
console.log("This client instance is ready!");
}
});
These are default values for the global configurations options. You should generally update these before you create your clients.
var _globalConfig = {
// SWF URL, relative to the page. Default value will be "ClipAndFile.swf"
// under the same path as the ClipAndFile JS file.
swfPath: _swfPath,
// SWF inbound scripting policy: page domains that the SWF should trust.
// (single string, or array of strings)
trustedDomains: window.location.host ? [window.location.host] : [],
// Include a "noCache" query parameter on requests for the SWF.
cacheBust: true,
// Enable use of the fancy "Desktop" clipboard, even on Linux where it is
// known to suck.
forceEnhancedClipboard: false,
// How many milliseconds to wait for the Flash SWF to load and respond before assuming that
// Flash is deactivated (e.g. click-to-play) in the user's browser. If you don't care about
// how long it takes to load the SWF, you can set this to `null`.
flashLoadTimeout: 30000,
// Setting this to `false` would allow users to handle calling `ClipAndFile.activate(...);`
// themselves instead of relying on our per-element `mouseover` handler.
autoActivate: true,
// Bubble synthetic events in JavaScript after they are received by the Flash object.
bubbleEvents: true,
// Sets the ID of the `div` encapsulating the Flash object.
// Value is validated against the [HTML4 spec for `ID` tokens][valid_ids].
containerId: "global-zeroclipboard-html-bridge",
// Sets the class of the `div` encapsulating the Flash object.
containerClass: "global-zeroclipboard-container",
// Sets the ID and name of the Flash `object` element.
// Value is validated against the [HTML4 spec for `ID` and `Name` tokens][valid_ids].
swfObjectId: "global-zeroclipboard-flash-bridge",
// The class used to indicate that a clipped element is being hovered over.
hoverClass: "zeroclipboard-is-hover",
// The class used to indicate that a clipped element is active (is being clicked).
activeClass: "zeroclipboard-is-active",
// Forcibly set the hand cursor ("pointer") for all clipped elements.
// IMPORTANT: This configuration value CAN be modified while a SWF is actively embedded.
forceHandCursor: false,
// Sets the title of the `div` encapsulating the Flash object.
// IMPORTANT: This configuration value CAN be modified while a SWF is actively embedded.
title: null,
// The z-index used by the Flash object.
// Max value (32-bit): 2147483647.
// IMPORTANT: This configuration value CAN be modified while a SWF is actively embedded.
zIndex: 999999999
};
You can override the defaults by making a call like ClipAndFile.config({ swfPath: "new/path" });
before you create any clients.
This allows other SWF files and HTML pages from the allowed domains to access/call publicly exposed ActionScript code,
e.g. functions shared via ExternalInterface.addCallback
. In other words, it controls the SWF inbound scripting access.
If your ClipAndFile SWF is served from a different origin/domain than your page, you need to tell the SWF that it's
OK to trust your page. The default value of [window.location.host]
is almost always what you will want unless
you specifically want the SWF to communicate with pages from other domains (e.g. in iframe
s or child windows).
For more information about trusted domains, consult the official Flash documentation for flash.system.Security.allowDomain(...)
.
The allowScriptAccess
parameter (for Flash embedding markup) allows the SWF file to access/call JavaScript/HTML functionality of
HTML pages on allowed domains, e.g. invoking functions via ExternalInterface.call
. In other words, it controls the SWF outbound
scripting access.
As of version v2.0.0-alpha.2
, the allowScriptAccess
configuration option no longer exists. The appropriate value will be determined
immediately before the Flash object is embedded on the page. The value is based on a relationship between the current
domain (window.location.host
) and the value of the trustedDomains
configuration option.
For more information about allowScriptAccess
, consult the official Flash documentation.
ClipAndFile was intentionally configured to not allow the SWF to be served from a secure domain (HTTPS) but scripted by an insecure domain (HTTP).
If you find yourself in this situation (as in Issue #170), please consider the following options:
- Serve the SWF over HTTP instead of HTTPS. If the page's protocol can vary (e.g. authorized/unauthorized, staging/production, etc.), you should include add the SWF with a relative protocol (
//s3.amazonaws.com/blah/ClipAndFile.swf
) instead of an absolute protocol (https://s3.amazonaws.com/blah/ClipAndFile.swf
). - Serve the page over HTTPS instead of HTTP. If the page's protocol can vary, see the note on the previous option (1).
- Update ClipAndFile's ActionScript codebase to call the
allowInsecureDomain
method, then recompile the SWF with your custom changes.