Changeset 1208875
- Timestamp:
- 07/29/2015 09:52:45 AM (11 years ago)
- Location:
- wr-contactform/trunk/assets/3rd-party/zeroclipboard
- Files:
-
- 2 edited
-
ZeroClipboard.js (modified) (7 diffs)
-
ZeroClipboard.swf (modified) (previous)
Legend:
- Unmodified
- Added
- Removed
-
wr-contactform/trunk/assets/3rd-party/zeroclipboard/ZeroClipboard.js
r1199207 r1208875 1 1 /*! 2 * ZeroClipboard3 * The ZeroClipboard library provides an easy way to copy text to the clipboard using an invisible Adobe Flash movie and a JavaScript interface.4 * Copyright (c) 2009-2014 Jon Rohan, James M. Greene5 * Licensed MIT6 * http://zeroclipboard.org/7 * v2.2.0 8 */9 (function(window , undefined) {2 * ZeroClipboard 3 * The ZeroClipboard library provides an easy way to copy text to the clipboard using an invisible Adobe Flash movie and a JavaScript interface. 4 * Copyright (c) 2014 Jon Rohan, James M. Greene 5 * Licensed MIT 6 * http://zeroclipboard.org/ 7 * v1.3.5 8 */ 9 (function(window) { 10 10 "use strict"; 11 /** 12 * Store references to critically important global functions that may be 13 * overridden on certain web pages. 14 */ 15 var _window = window, _document = _window.document, _navigator = _window.navigator, _setTimeout = _window.setTimeout, _clearTimeout = _window.clearTimeout, _setInterval = _window.setInterval, _clearInterval = _window.clearInterval, _getComputedStyle = _window.getComputedStyle, _encodeURIComponent = _window.encodeURIComponent, _ActiveXObject = _window.ActiveXObject, _Error = _window.Error, _parseInt = _window.Number.parseInt || _window.parseInt, _parseFloat = _window.Number.parseFloat || _window.parseFloat, _isNaN = _window.Number.isNaN || _window.isNaN, _now = _window.Date.now, _keys = _window.Object.keys, _defineProperty = _window.Object.defineProperty, _hasOwn = _window.Object.prototype.hasOwnProperty, _slice = _window.Array.prototype.slice, _unwrap = function() { 16 var unwrapper = function(el) { 17 return el; 18 }; 19 if (typeof _window.wrap === "function" && typeof _window.unwrap === "function") { 20 try { 21 var div = _document.createElement("div"); 22 var unwrappedDiv = _window.unwrap(div); 23 if (div.nodeType === 1 && unwrappedDiv && unwrappedDiv.nodeType === 1) { 24 unwrapper = _window.unwrap; 25 } 26 } catch (e) {} 27 } 28 return unwrapper; 29 }(); 30 /** 31 * Convert an `arguments` object into an Array. 32 * 33 * @returns The arguments as an Array 34 * @private 35 */ 36 var _args = function(argumentsObj) { 37 return _slice.call(argumentsObj, 0); 38 }; 39 /** 40 * Shallow-copy the owned, enumerable properties of one object over to another, similar to jQuery's `$.extend`. 41 * 42 * @returns The target object, augmented 43 * @private 44 */ 45 var _extend = function() { 46 var i, len, arg, prop, src, copy, args = _args(arguments), target = args[0] || {}; 47 for (i = 1, len = args.length; i < len; i++) { 48 if ((arg = args[i]) != null) { 49 for (prop in arg) { 50 if (_hasOwn.call(arg, prop)) { 51 src = target[prop]; 52 copy = arg[prop]; 53 if (target !== copy && copy !== undefined) { 54 target[prop] = copy; 55 } 56 } 57 } 58 } 59 } 60 return target; 61 }; 62 /** 63 * Return a deep copy of the source object or array. 64 * 65 * @returns Object or Array 66 * @private 67 */ 68 var _deepCopy = function(source) { 69 var copy, i, len, prop; 70 if (typeof source !== "object" || source == null || typeof source.nodeType === "number") { 71 copy = source; 72 } else if (typeof source.length === "number") { 73 copy = []; 74 for (i = 0, len = source.length; i < len; i++) { 75 if (_hasOwn.call(source, i)) { 76 copy[i] = _deepCopy(source[i]); 77 } 78 } 79 } else { 80 copy = {}; 81 for (prop in source) { 82 if (_hasOwn.call(source, prop)) { 83 copy[prop] = _deepCopy(source[prop]); 84 } 85 } 86 } 87 return copy; 88 }; 89 /** 90 * Makes a shallow copy of `obj` (like `_extend`) but filters its properties based on a list of `keys` to keep. 91 * The inverse of `_omit`, mostly. The big difference is that these properties do NOT need to be enumerable to 92 * be kept. 93 * 94 * @returns A new filtered object. 95 * @private 96 */ 97 var _pick = function(obj, keys) { 98 var newObj = {}; 99 for (var i = 0, len = keys.length; i < len; i++) { 100 if (keys[i] in obj) { 101 newObj[keys[i]] = obj[keys[i]]; 102 } 103 } 104 return newObj; 105 }; 106 /** 107 * Makes a shallow copy of `obj` (like `_extend`) but filters its properties based on a list of `keys` to omit. 108 * The inverse of `_pick`. 109 * 110 * @returns A new filtered object. 111 * @private 112 */ 113 var _omit = function(obj, keys) { 114 var newObj = {}; 115 for (var prop in obj) { 116 if (keys.indexOf(prop) === -1) { 117 newObj[prop] = obj[prop]; 118 } 119 } 120 return newObj; 121 }; 122 /** 123 * Remove all owned, enumerable properties from an object. 124 * 125 * @returns The original object without its owned, enumerable properties. 126 * @private 127 */ 128 var _deleteOwnProperties = function(obj) { 129 if (obj) { 130 for (var prop in obj) { 131 if (_hasOwn.call(obj, prop)) { 132 delete obj[prop]; 133 } 134 } 135 } 136 return obj; 137 }; 138 /** 139 * Determine if an element is contained within another element. 140 * 141 * @returns Boolean 142 * @private 143 */ 144 var _containedBy = function(el, ancestorEl) { 145 if (el && el.nodeType === 1 && el.ownerDocument && ancestorEl && (ancestorEl.nodeType === 1 && ancestorEl.ownerDocument && ancestorEl.ownerDocument === el.ownerDocument || ancestorEl.nodeType === 9 && !ancestorEl.ownerDocument && ancestorEl === el.ownerDocument)) { 146 do { 147 if (el === ancestorEl) { 148 return true; 149 } 150 el = el.parentNode; 151 } while (el); 152 } 153 return false; 154 }; 155 /** 156 * Get the URL path's parent directory. 157 * 158 * @returns String or `undefined` 159 * @private 160 */ 161 var _getDirPathOfUrl = function(url) { 162 var dir; 163 if (typeof url === "string" && url) { 164 dir = url.split("#")[0].split("?")[0]; 165 dir = url.slice(0, url.lastIndexOf("/") + 1); 166 } 167 return dir; 168 }; 169 /** 170 * Get the current script's URL by throwing an `Error` and analyzing it. 171 * 172 * @returns String or `undefined` 173 * @private 174 */ 175 var _getCurrentScriptUrlFromErrorStack = function(stack) { 176 var url, matches; 177 if (typeof stack === "string" && stack) { 178 matches = stack.match(/^(?:|[^:@]*@|.+\)@(?=http[s]?|file)|.+?\s+(?: at |@)(?:[^:\(]+ )*[\(]?)((?:http[s]?|file):\/\/[\/]?.+?\/[^:\)]*?)(?::\d+)(?::\d+)?/); 179 if (matches && matches[1]) { 180 url = matches[1]; 181 } else { 182 matches = stack.match(/\)@((?:http[s]?|file):\/\/[\/]?.+?\/[^:\)]*?)(?::\d+)(?::\d+)?/); 183 if (matches && matches[1]) { 184 url = matches[1]; 185 } 186 } 187 } 188 return url; 189 }; 190 /** 191 * Get the current script's URL by throwing an `Error` and analyzing it. 192 * 193 * @returns String or `undefined` 194 * @private 195 */ 196 var _getCurrentScriptUrlFromError = function() { 197 var url, err; 198 try { 199 throw new _Error(); 200 } catch (e) { 201 err = e; 202 } 203 if (err) { 204 url = err.sourceURL || err.fileName || _getCurrentScriptUrlFromErrorStack(err.stack); 205 } 206 return url; 207 }; 208 /** 209 * Get the current script's URL. 210 * 211 * @returns String or `undefined` 212 * @private 213 */ 214 var _getCurrentScriptUrl = function() { 215 var jsPath, scripts, i; 216 if (_document.currentScript && (jsPath = _document.currentScript.src)) { 217 return jsPath; 218 } 219 scripts = _document.getElementsByTagName("script"); 220 if (scripts.length === 1) { 221 return scripts[0].src || undefined; 222 } 223 if ("readyState" in scripts[0]) { 224 for (i = scripts.length; i--; ) { 225 if (scripts[i].readyState === "interactive" && (jsPath = scripts[i].src)) { 226 return jsPath; 227 } 228 } 229 } 230 if (_document.readyState === "loading" && (jsPath = scripts[scripts.length - 1].src)) { 231 return jsPath; 232 } 233 if (jsPath = _getCurrentScriptUrlFromError()) { 234 return jsPath; 235 } 236 return undefined; 237 }; 238 /** 239 * Get the unanimous parent directory of ALL script tags. 240 * If any script tags are either (a) inline or (b) from differing parent 241 * directories, this method must return `undefined`. 242 * 243 * @returns String or `undefined` 244 * @private 245 */ 246 var _getUnanimousScriptParentDir = function() { 247 var i, jsDir, jsPath, scripts = _document.getElementsByTagName("script"); 248 for (i = scripts.length; i--; ) { 249 if (!(jsPath = scripts[i].src)) { 250 jsDir = null; 251 break; 252 } 253 jsPath = _getDirPathOfUrl(jsPath); 254 if (jsDir == null) { 255 jsDir = jsPath; 256 } else if (jsDir !== jsPath) { 257 jsDir = null; 258 break; 259 } 260 } 261 return jsDir || undefined; 262 }; 263 /** 264 * Get the presumed location of the "ZeroClipboard.swf" file, based on the location 265 * of the executing JavaScript file (e.g. "ZeroClipboard.js", etc.). 266 * 267 * @returns String 268 * @private 269 */ 270 var _getDefaultSwfPath = function() { 271 var jsDir = _getDirPathOfUrl(_getCurrentScriptUrl()) || _getUnanimousScriptParentDir() || ""; 272 return jsDir + "ZeroClipboard.swf"; 273 }; 274 /** 275 * Keep track of if the page is framed (in an `iframe`). This can never change. 276 * @private 277 */ 278 var _pageIsFramed = function() { 279 return window.opener == null && (!!window.top && window != window.top || !!window.parent && window != window.parent); 280 }(); 281 /** 282 * Keep track of the state of the Flash object. 283 * @private 284 */ 285 var _flashState = { 11 var currentElement; 12 var flashState = { 286 13 bridge: null, 287 14 version: "0.0.0", 288 pluginType: "unknown",289 15 disabled: null, 290 16 outdated: null, 291 sandboxed: null,292 unavailable: null,293 degraded: null,294 deactivated: null,295 overdue: null,296 17 ready: null 297 18 }; 298 /**299 * The minimum Flash Player version required to use ZeroClipboard completely.300 * @readonly301 * @private302 */303 var _minimumFlashVersion = "11.0.0";304 /**305 * The ZeroClipboard library version number, as reported by Flash, at the time the SWF was compiled.306 */307 var _zcSwfVersion;308 /**309 * Keep track of all event listener registrations.310 * @private311 */312 var _handlers = {};313 /**314 * Keep track of the currently activated element.315 * @private316 */317 var _currentElement;318 /**319 * Keep track of the element that was activated when a `copy` process started.320 * @private321 */322 var _copyTarget;323 /**324 * Keep track of data for the pending clipboard transaction.325 * @private326 */327 19 var _clipData = {}; 328 /** 329 * Keep track of data formats for the pending clipboard transaction. 330 * @private 331 */ 332 var _clipDataFormatMap = null; 333 /** 334 * Keep track of the Flash availability check timeout. 335 * @private 336 */ 337 var _flashCheckTimeout = 0; 338 /** 339 * Keep track of SWF network errors interval polling. 340 * @private 341 */ 342 var _swfFallbackCheckInterval = 0; 343 /** 344 * The `message` store for events 345 * @private 346 */ 347 var _eventMessages = { 348 ready: "Flash communication is established", 349 error: { 350 "flash-disabled": "Flash is disabled or not installed. May also be attempting to run Flash in a sandboxed iframe, which is impossible.", 351 "flash-outdated": "Flash is too outdated to support ZeroClipboard", 352 "flash-sandboxed": "Attempting to run Flash in a sandboxed iframe, which is impossible", 353 "flash-unavailable": "Flash is unable to communicate bidirectionally with JavaScript", 354 "flash-degraded": "Flash is unable to preserve data fidelity when communicating with JavaScript", 355 "flash-deactivated": "Flash is too outdated for your browser and/or is configured as click-to-activate.\nThis may also mean that the ZeroClipboard SWF object could not be loaded, so please check your `swfPath` configuration and/or network connectivity.\nMay also be attempting to run Flash in a sandboxed iframe, which is impossible.", 356 "flash-overdue": "Flash communication was established but NOT within the acceptable time limit", 357 "version-mismatch": "ZeroClipboard JS version number does not match ZeroClipboard SWF version number", 358 "clipboard-error": "At least one error was thrown while ZeroClipboard was attempting to inject your data into the clipboard", 359 "config-mismatch": "ZeroClipboard configuration does not match Flash's reality", 360 "swf-not-found": "The ZeroClipboard SWF object could not be loaded, so please check your `swfPath` configuration and/or network connectivity" 361 } 362 }; 363 /** 364 * The `name`s of `error` events that can only occur is Flash has at least 365 * been able to load the SWF successfully. 366 * @private 367 */ 368 var _errorsThatOnlyOccurAfterFlashLoads = [ "flash-unavailable", "flash-degraded", "flash-overdue", "version-mismatch", "config-mismatch", "clipboard-error" ]; 369 /** 370 * The `name`s of `error` events that should likely result in the `_flashState` 371 * variable's property values being updated. 372 * @private 373 */ 374 var _flashStateErrorNames = [ "flash-disabled", "flash-outdated", "flash-sandboxed", "flash-unavailable", "flash-degraded", "flash-deactivated", "flash-overdue" ]; 375 /** 376 * A RegExp to match the `name` property of `error` events related to Flash. 377 * @private 378 */ 379 var _flashStateErrorNameMatchingRegex = new RegExp("^flash-(" + _flashStateErrorNames.map(function(errorName) { 380 return errorName.replace(/^flash-/, ""); 381 }).join("|") + ")$"); 382 /** 383 * A RegExp to match the `name` property of `error` events related to Flash, 384 * which is enabled. 385 * @private 386 */ 387 var _flashStateEnabledErrorNameMatchingRegex = new RegExp("^flash-(" + _flashStateErrorNames.slice(1).map(function(errorName) { 388 return errorName.replace(/^flash-/, ""); 389 }).join("|") + ")$"); 390 /** 391 * ZeroClipboard configuration defaults for the Core module. 392 * @private 393 */ 394 var _globalConfig = { 395 swfPath: _getDefaultSwfPath(), 396 trustedDomains: window.location.host ? [ window.location.host ] : [], 397 cacheBust: true, 398 forceEnhancedClipboard: false, 399 flashLoadTimeout: 3e4, 400 autoActivate: true, 401 bubbleEvents: true, 402 containerId: "global-zeroclipboard-html-bridge", 403 containerClass: "global-zeroclipboard-container", 404 swfObjectId: "global-zeroclipboard-flash-bridge", 405 hoverClass: "zeroclipboard-is-hover", 406 activeClass: "zeroclipboard-is-active", 407 forceHandCursor: false, 408 title: null, 409 zIndex: 999999999 410 }; 411 /** 412 * The underlying implementation of `ZeroClipboard.config`. 413 * @private 414 */ 415 var _config = function(options) { 416 if (typeof options === "object" && options !== null) { 417 for (var prop in options) { 418 if (_hasOwn.call(options, prop)) { 419 if (/^(?:forceHandCursor|title|zIndex|bubbleEvents)$/.test(prop)) { 420 _globalConfig[prop] = options[prop]; 421 } else if (_flashState.bridge == null) { 422 if (prop === "containerId" || prop === "swfObjectId") { 423 if (_isValidHtml4Id(options[prop])) { 424 _globalConfig[prop] = options[prop]; 425 } else { 426 throw new Error("The specified `" + prop + "` value is not valid as an HTML4 Element ID"); 427 } 428 } else { 429 _globalConfig[prop] = options[prop]; 20 var clientIdCounter = 0; 21 var _clientMeta = {}; 22 var elementIdCounter = 0; 23 var _elementMeta = {}; 24 var _amdModuleId = null; 25 var _cjsModuleId = null; 26 var _swfPath = function() { 27 var i, jsDir, tmpJsPath, jsPath, swfPath = "ZeroClipboard.swf"; 28 if (document.currentScript && (jsPath = document.currentScript.src)) {} else { 29 var scripts = document.getElementsByTagName("script"); 30 if ("readyState" in scripts[0]) { 31 for (i = scripts.length; i--; ) { 32 if (scripts[i].readyState === "interactive" && (jsPath = scripts[i].src)) { 33 break; 34 } 35 } 36 } else if (document.readyState === "loading") { 37 jsPath = scripts[scripts.length - 1].src; 38 } else { 39 for (i = scripts.length; i--; ) { 40 tmpJsPath = scripts[i].src; 41 if (!tmpJsPath) { 42 jsDir = null; 43 break; 44 } 45 tmpJsPath = tmpJsPath.split("#")[0].split("?")[0]; 46 tmpJsPath = tmpJsPath.slice(0, tmpJsPath.lastIndexOf("/") + 1); 47 if (jsDir == null) { 48 jsDir = tmpJsPath; 49 } else if (jsDir !== tmpJsPath) { 50 jsDir = null; 51 break; 52 } 53 } 54 if (jsDir !== null) { 55 jsPath = jsDir; 56 } 57 } 58 } 59 if (jsPath) { 60 jsPath = jsPath.split("#")[0].split("?")[0]; 61 swfPath = jsPath.slice(0, jsPath.lastIndexOf("/") + 1) + swfPath; 62 } 63 return swfPath; 64 }(); 65 var _camelizeCssPropName = function() { 66 var matcherRegex = /\-([a-z])/g, replacerFn = function(match, group) { 67 return group.toUpperCase(); 68 }; 69 return function(prop) { 70 return prop.replace(matcherRegex, replacerFn); 71 }; 72 }(); 73 var _getStyle = function(el, prop) { 74 var value, camelProp, tagName, possiblePointers, i, len; 75 if (window.getComputedStyle) { 76 value = window.getComputedStyle(el, null).getPropertyValue(prop); 77 } else { 78 camelProp = _camelizeCssPropName(prop); 79 if (el.currentStyle) { 80 value = el.currentStyle[camelProp]; 81 } else { 82 value = el.style[camelProp]; 83 } 84 } 85 if (prop === "cursor") { 86 if (!value || value === "auto") { 87 tagName = el.tagName.toLowerCase(); 88 if (tagName === "a") { 89 return "pointer"; 90 } 91 } 92 } 93 return value; 94 }; 95 var _elementMouseOver = function(event) { 96 if (!event) { 97 event = window.event; 98 } 99 var target; 100 if (this !== window) { 101 target = this; 102 } else if (event.target) { 103 target = event.target; 104 } else if (event.srcElement) { 105 target = event.srcElement; 106 } 107 ZeroClipboard.activate(target); 108 }; 109 var _addEventHandler = function(element, method, func) { 110 if (!element || element.nodeType !== 1) { 111 return; 112 } 113 if (element.addEventListener) { 114 element.addEventListener(method, func, false); 115 } else if (element.attachEvent) { 116 element.attachEvent("on" + method, func); 117 } 118 }; 119 var _removeEventHandler = function(element, method, func) { 120 if (!element || element.nodeType !== 1) { 121 return; 122 } 123 if (element.removeEventListener) { 124 element.removeEventListener(method, func, false); 125 } else if (element.detachEvent) { 126 element.detachEvent("on" + method, func); 127 } 128 }; 129 var _addClass = function(element, value) { 130 if (!element || element.nodeType !== 1) { 131 return element; 132 } 133 if (element.classList) { 134 if (!element.classList.contains(value)) { 135 element.classList.add(value); 136 } 137 return element; 138 } 139 if (value && typeof value === "string") { 140 var classNames = (value || "").split(/\s+/); 141 if (element.nodeType === 1) { 142 if (!element.className) { 143 element.className = value; 144 } else { 145 var className = " " + element.className + " ", setClass = element.className; 146 for (var c = 0, cl = classNames.length; c < cl; c++) { 147 if (className.indexOf(" " + classNames[c] + " ") < 0) { 148 setClass += " " + classNames[c]; 430 149 } 431 150 } 432 } 433 } 434 } 435 if (typeof options === "string" && options) { 436 if (_hasOwn.call(_globalConfig, options)) { 437 return _globalConfig[options]; 438 } 439 return; 440 } 441 return _deepCopy(_globalConfig); 442 }; 443 /** 444 * The underlying implementation of `ZeroClipboard.state`. 445 * @private 446 */ 447 var _state = function() { 448 _detectSandbox(); 449 return { 450 browser: _pick(_navigator, [ "userAgent", "platform", "appName" ]), 451 flash: _omit(_flashState, [ "bridge" ]), 452 zeroclipboard: { 453 version: ZeroClipboard.version, 454 config: ZeroClipboard.config() 455 } 151 element.className = setClass.replace(/^\s+|\s+$/g, ""); 152 } 153 } 154 } 155 return element; 156 }; 157 var _removeClass = function(element, value) { 158 if (!element || element.nodeType !== 1) { 159 return element; 160 } 161 if (element.classList) { 162 if (element.classList.contains(value)) { 163 element.classList.remove(value); 164 } 165 return element; 166 } 167 if (value && typeof value === "string" || value === undefined) { 168 var classNames = (value || "").split(/\s+/); 169 if (element.nodeType === 1 && element.className) { 170 if (value) { 171 var className = (" " + element.className + " ").replace(/[\n\t]/g, " "); 172 for (var c = 0, cl = classNames.length; c < cl; c++) { 173 className = className.replace(" " + classNames[c] + " ", " "); 174 } 175 element.className = className.replace(/^\s+|\s+$/g, ""); 176 } else { 177 element.className = ""; 178 } 179 } 180 } 181 return element; 182 }; 183 var _getZoomFactor = function() { 184 var rect, physicalWidth, logicalWidth, zoomFactor = 1; 185 if (typeof document.body.getBoundingClientRect === "function") { 186 rect = document.body.getBoundingClientRect(); 187 physicalWidth = rect.right - rect.left; 188 logicalWidth = document.body.offsetWidth; 189 zoomFactor = Math.round(physicalWidth / logicalWidth * 100) / 100; 190 } 191 return zoomFactor; 192 }; 193 var _getDOMObjectPosition = function(obj, defaultZIndex) { 194 var info = { 195 left: 0, 196 top: 0, 197 width: 0, 198 height: 0, 199 zIndex: _getSafeZIndex(defaultZIndex) - 1 456 200 }; 457 }; 458 /** 459 * The underlying implementation of `ZeroClipboard.isFlashUnusable`. 460 * @private 461 */ 462 var _isFlashUnusable = function() { 463 return !!(_flashState.disabled || _flashState.outdated || _flashState.sandboxed || _flashState.unavailable || _flashState.degraded || _flashState.deactivated); 464 }; 465 /** 466 * The underlying implementation of `ZeroClipboard.on`. 467 * @private 468 */ 469 var _on = function(eventType, listener) { 470 var i, len, events, added = {}; 471 if (typeof eventType === "string" && eventType) { 472 events = eventType.toLowerCase().split(/\s+/); 473 } else if (typeof eventType === "object" && eventType && typeof listener === "undefined") { 474 for (i in eventType) { 475 if (_hasOwn.call(eventType, i) && typeof i === "string" && i && typeof eventType[i] === "function") { 476 ZeroClipboard.on(i, eventType[i]); 477 } 478 } 479 } 480 if (events && events.length) { 481 for (i = 0, len = events.length; i < len; i++) { 482 eventType = events[i].replace(/^on/, ""); 483 added[eventType] = true; 484 if (!_handlers[eventType]) { 485 _handlers[eventType] = []; 486 } 487 _handlers[eventType].push(listener); 488 } 489 if (added.ready && _flashState.ready) { 490 ZeroClipboard.emit({ 491 type: "ready" 492 }); 493 } 494 if (added.error) { 495 for (i = 0, len = _flashStateErrorNames.length; i < len; i++) { 496 if (_flashState[_flashStateErrorNames[i].replace(/^flash-/, "")] === true) { 497 ZeroClipboard.emit({ 498 type: "error", 499 name: _flashStateErrorNames[i] 500 }); 201 if (obj.getBoundingClientRect) { 202 var rect = obj.getBoundingClientRect(); 203 var pageXOffset, pageYOffset, zoomFactor; 204 if ("pageXOffset" in window && "pageYOffset" in window) { 205 pageXOffset = window.pageXOffset; 206 pageYOffset = window.pageYOffset; 207 } else { 208 zoomFactor = _getZoomFactor(); 209 pageXOffset = Math.round(document.documentElement.scrollLeft / zoomFactor); 210 pageYOffset = Math.round(document.documentElement.scrollTop / zoomFactor); 211 } 212 var leftBorderWidth = document.documentElement.clientLeft || 0; 213 var topBorderWidth = document.documentElement.clientTop || 0; 214 info.left = rect.left + pageXOffset - leftBorderWidth; 215 info.top = rect.top + pageYOffset - topBorderWidth; 216 info.width = "width" in rect ? rect.width : rect.right - rect.left; 217 info.height = "height" in rect ? rect.height : rect.bottom - rect.top; 218 } 219 return info; 220 }; 221 var _cacheBust = function(path, options) { 222 var cacheBust = options == null || options && options.cacheBust === true && options.useNoCache === true; 223 if (cacheBust) { 224 return (path.indexOf("?") === -1 ? "?" : "&") + "noCache=" + new Date().getTime(); 225 } else { 226 return ""; 227 } 228 }; 229 var _vars = function(options) { 230 var i, len, domain, str = [], domains = [], trustedOriginsExpanded = []; 231 if (options.trustedOrigins) { 232 if (typeof options.trustedOrigins === "string") { 233 domains.push(options.trustedOrigins); 234 } else if (typeof options.trustedOrigins === "object" && "length" in options.trustedOrigins) { 235 domains = domains.concat(options.trustedOrigins); 236 } 237 } 238 if (options.trustedDomains) { 239 if (typeof options.trustedDomains === "string") { 240 domains.push(options.trustedDomains); 241 } else if (typeof options.trustedDomains === "object" && "length" in options.trustedDomains) { 242 domains = domains.concat(options.trustedDomains); 243 } 244 } 245 if (domains.length) { 246 for (i = 0, len = domains.length; i < len; i++) { 247 if (domains.hasOwnProperty(i) && domains[i] && typeof domains[i] === "string") { 248 domain = _extractDomain(domains[i]); 249 if (!domain) { 250 continue; 251 } 252 if (domain === "*") { 253 trustedOriginsExpanded = [ domain ]; 501 254 break; 502 255 } 503 } 504 if (_zcSwfVersion !== undefined && ZeroClipboard.version !== _zcSwfVersion) { 505 ZeroClipboard.emit({ 506 type: "error", 507 name: "version-mismatch", 508 jsVersion: ZeroClipboard.version, 509 swfVersion: _zcSwfVersion 510 }); 511 } 512 } 513 } 514 return ZeroClipboard; 515 }; 516 /** 517 * The underlying implementation of `ZeroClipboard.off`. 518 * @private 519 */ 520 var _off = function(eventType, listener) { 521 var i, len, foundIndex, events, perEventHandlers; 522 if (arguments.length === 0) { 523 events = _keys(_handlers); 524 } else if (typeof eventType === "string" && eventType) { 525 events = eventType.split(/\s+/); 526 } else if (typeof eventType === "object" && eventType && typeof listener === "undefined") { 527 for (i in eventType) { 528 if (_hasOwn.call(eventType, i) && typeof i === "string" && i && typeof eventType[i] === "function") { 529 ZeroClipboard.off(i, eventType[i]); 530 } 531 } 532 } 533 if (events && events.length) { 534 for (i = 0, len = events.length; i < len; i++) { 535 eventType = events[i].toLowerCase().replace(/^on/, ""); 536 perEventHandlers = _handlers[eventType]; 537 if (perEventHandlers && perEventHandlers.length) { 538 if (listener) { 539 foundIndex = perEventHandlers.indexOf(listener); 540 while (foundIndex !== -1) { 541 perEventHandlers.splice(foundIndex, 1); 542 foundIndex = perEventHandlers.indexOf(listener, foundIndex); 543 } 544 } else { 545 perEventHandlers.length = 0; 546 } 547 } 548 } 549 } 550 return ZeroClipboard; 551 }; 552 /** 553 * The underlying implementation of `ZeroClipboard.handlers`. 554 * @private 555 */ 556 var _listeners = function(eventType) { 557 var copy; 558 if (typeof eventType === "string" && eventType) { 559 copy = _deepCopy(_handlers[eventType]) || null; 560 } else { 561 copy = _deepCopy(_handlers); 562 } 563 return copy; 564 }; 565 /** 566 * The underlying implementation of `ZeroClipboard.emit`. 567 * @private 568 */ 569 var _emit = function(event) { 570 var eventCopy, returnVal, tmp; 571 event = _createEvent(event); 572 if (!event) { 573 return; 574 } 575 if (_preprocessEvent(event)) { 576 return; 577 } 578 if (event.type === "ready" && _flashState.overdue === true) { 579 return ZeroClipboard.emit({ 580 type: "error", 581 name: "flash-overdue" 582 }); 583 } 584 eventCopy = _extend({}, event); 585 _dispatchCallbacks.call(this, eventCopy); 586 if (event.type === "copy") { 587 tmp = _mapClipDataToFlash(_clipData); 588 returnVal = tmp.data; 589 _clipDataFormatMap = tmp.formatMap; 590 } 591 return returnVal; 592 }; 593 /** 594 * The underlying implementation of `ZeroClipboard.create`. 595 * @private 596 */ 597 var _create = function() { 598 var previousState = _flashState.sandboxed; 599 _detectSandbox(); 600 if (typeof _flashState.ready !== "boolean") { 601 _flashState.ready = false; 602 } 603 if (_flashState.sandboxed !== previousState && _flashState.sandboxed === true) { 604 _flashState.ready = false; 605 ZeroClipboard.emit({ 606 type: "error", 607 name: "flash-sandboxed" 608 }); 609 } else if (!ZeroClipboard.isFlashUnusable() && _flashState.bridge === null) { 610 var maxWait = _globalConfig.flashLoadTimeout; 611 if (typeof maxWait === "number" && maxWait >= 0) { 612 _flashCheckTimeout = _setTimeout(function() { 613 if (typeof _flashState.deactivated !== "boolean") { 614 _flashState.deactivated = true; 615 } 616 if (_flashState.deactivated === true) { 617 ZeroClipboard.emit({ 618 type: "error", 619 name: "flash-deactivated" 620 }); 621 } 622 }, maxWait); 623 } 624 _flashState.overdue = false; 625 _embedSwf(); 626 } 627 }; 628 /** 629 * The underlying implementation of `ZeroClipboard.destroy`. 630 * @private 631 */ 632 var _destroy = function() { 633 ZeroClipboard.clearData(); 634 ZeroClipboard.blur(); 635 ZeroClipboard.emit("destroy"); 636 _unembedSwf(); 637 ZeroClipboard.off(); 638 }; 639 /** 640 * The underlying implementation of `ZeroClipboard.setData`. 641 * @private 642 */ 643 var _setData = function(format, data) { 644 var dataObj; 645 if (typeof format === "object" && format && typeof data === "undefined") { 646 dataObj = format; 647 ZeroClipboard.clearData(); 648 } else if (typeof format === "string" && format) { 649 dataObj = {}; 650 dataObj[format] = data; 651 } else { 652 return; 653 } 654 for (var dataFormat in dataObj) { 655 if (typeof dataFormat === "string" && dataFormat && _hasOwn.call(dataObj, dataFormat) && typeof dataObj[dataFormat] === "string" && dataObj[dataFormat]) { 656 _clipData[dataFormat] = dataObj[dataFormat]; 657 } 658 } 659 }; 660 /** 661 * The underlying implementation of `ZeroClipboard.clearData`. 662 * @private 663 */ 664 var _clearData = function(format) { 665 if (typeof format === "undefined") { 666 _deleteOwnProperties(_clipData); 667 _clipDataFormatMap = null; 668 } else if (typeof format === "string" && _hasOwn.call(_clipData, format)) { 669 delete _clipData[format]; 670 } 671 }; 672 /** 673 * The underlying implementation of `ZeroClipboard.getData`. 674 * @private 675 */ 676 var _getData = function(format) { 677 if (typeof format === "undefined") { 678 return _deepCopy(_clipData); 679 } else if (typeof format === "string" && _hasOwn.call(_clipData, format)) { 680 return _clipData[format]; 681 } 682 }; 683 /** 684 * The underlying implementation of `ZeroClipboard.focus`/`ZeroClipboard.activate`. 685 * @private 686 */ 687 var _focus = function(element) { 688 if (!(element && element.nodeType === 1)) { 689 return; 690 } 691 if (_currentElement) { 692 _removeClass(_currentElement, _globalConfig.activeClass); 693 if (_currentElement !== element) { 694 _removeClass(_currentElement, _globalConfig.hoverClass); 695 } 696 } 697 _currentElement = element; 698 _addClass(element, _globalConfig.hoverClass); 699 var newTitle = element.getAttribute("title") || _globalConfig.title; 700 if (typeof newTitle === "string" && newTitle) { 701 var htmlBridge = _getHtmlBridge(_flashState.bridge); 702 if (htmlBridge) { 703 htmlBridge.setAttribute("title", newTitle); 704 } 705 } 706 var useHandCursor = _globalConfig.forceHandCursor === true || _getStyle(element, "cursor") === "pointer"; 707 _setHandCursor(useHandCursor); 708 _reposition(); 709 }; 710 /** 711 * The underlying implementation of `ZeroClipboard.blur`/`ZeroClipboard.deactivate`. 712 * @private 713 */ 714 var _blur = function() { 715 var htmlBridge = _getHtmlBridge(_flashState.bridge); 716 if (htmlBridge) { 717 htmlBridge.removeAttribute("title"); 718 htmlBridge.style.left = "0px"; 719 htmlBridge.style.top = "-9999px"; 720 htmlBridge.style.width = "1px"; 721 htmlBridge.style.height = "1px"; 722 } 723 if (_currentElement) { 724 _removeClass(_currentElement, _globalConfig.hoverClass); 725 _removeClass(_currentElement, _globalConfig.activeClass); 726 _currentElement = null; 727 } 728 }; 729 /** 730 * The underlying implementation of `ZeroClipboard.activeElement`. 731 * @private 732 */ 733 var _activeElement = function() { 734 return _currentElement || null; 735 }; 736 /** 737 * Check if a value is a valid HTML4 `ID` or `Name` token. 738 * @private 739 */ 740 var _isValidHtml4Id = function(id) { 741 return typeof id === "string" && id && /^[A-Za-z][A-Za-z0-9_:\-\.]*$/.test(id); 742 }; 743 /** 744 * Create or update an `event` object, based on the `eventType`. 745 * @private 746 */ 747 var _createEvent = function(event) { 748 var eventType; 749 if (typeof event === "string" && event) { 750 eventType = event; 751 event = {}; 752 } else if (typeof event === "object" && event && typeof event.type === "string" && event.type) { 753 eventType = event.type; 754 } 755 if (!eventType) { 756 return; 757 } 758 eventType = eventType.toLowerCase(); 759 if (!event.target && (/^(copy|aftercopy|_click)$/.test(eventType) || eventType === "error" && event.name === "clipboard-error")) { 760 event.target = _copyTarget; 761 } 762 _extend(event, { 763 type: eventType, 764 target: event.target || _currentElement || null, 765 relatedTarget: event.relatedTarget || null, 766 currentTarget: _flashState && _flashState.bridge || null, 767 timeStamp: event.timeStamp || _now() || null 768 }); 769 var msg = _eventMessages[event.type]; 770 if (event.type === "error" && event.name && msg) { 771 msg = msg[event.name]; 772 } 773 if (msg) { 774 event.message = msg; 775 } 776 if (event.type === "ready") { 777 _extend(event, { 778 target: null, 779 version: _flashState.version 780 }); 781 } 782 if (event.type === "error") { 783 if (_flashStateErrorNameMatchingRegex.test(event.name)) { 784 _extend(event, { 785 target: null, 786 minimumVersion: _minimumFlashVersion 787 }); 788 } 789 if (_flashStateEnabledErrorNameMatchingRegex.test(event.name)) { 790 _extend(event, { 791 version: _flashState.version 792 }); 793 } 794 } 795 if (event.type === "copy") { 796 event.clipboardData = { 797 setData: ZeroClipboard.setData, 798 clearData: ZeroClipboard.clearData 799 }; 800 } 801 if (event.type === "aftercopy") { 802 event = _mapClipResultsFromFlash(event, _clipDataFormatMap); 803 } 804 if (event.target && !event.relatedTarget) { 805 event.relatedTarget = _getRelatedTarget(event.target); 806 } 807 return _addMouseData(event); 808 }; 809 /** 810 * Get a relatedTarget from the target's `data-clipboard-target` attribute 811 * @private 812 */ 813 var _getRelatedTarget = function(targetEl) { 814 var relatedTargetId = targetEl && targetEl.getAttribute && targetEl.getAttribute("data-clipboard-target"); 815 return relatedTargetId ? _document.getElementById(relatedTargetId) : null; 816 }; 817 /** 818 * Add element and position data to `MouseEvent` instances 819 * @private 820 */ 821 var _addMouseData = function(event) { 822 if (event && /^_(?:click|mouse(?:over|out|down|up|move))$/.test(event.type)) { 823 var srcElement = event.target; 824 var fromElement = event.type === "_mouseover" && event.relatedTarget ? event.relatedTarget : undefined; 825 var toElement = event.type === "_mouseout" && event.relatedTarget ? event.relatedTarget : undefined; 826 var pos = _getElementPosition(srcElement); 827 var screenLeft = _window.screenLeft || _window.screenX || 0; 828 var screenTop = _window.screenTop || _window.screenY || 0; 829 var scrollLeft = _document.body.scrollLeft + _document.documentElement.scrollLeft; 830 var scrollTop = _document.body.scrollTop + _document.documentElement.scrollTop; 831 var pageX = pos.left + (typeof event._stageX === "number" ? event._stageX : 0); 832 var pageY = pos.top + (typeof event._stageY === "number" ? event._stageY : 0); 833 var clientX = pageX - scrollLeft; 834 var clientY = pageY - scrollTop; 835 var screenX = screenLeft + clientX; 836 var screenY = screenTop + clientY; 837 var moveX = typeof event.movementX === "number" ? event.movementX : 0; 838 var moveY = typeof event.movementY === "number" ? event.movementY : 0; 839 delete event._stageX; 840 delete event._stageY; 841 _extend(event, { 842 srcElement: srcElement, 843 fromElement: fromElement, 844 toElement: toElement, 845 screenX: screenX, 846 screenY: screenY, 847 pageX: pageX, 848 pageY: pageY, 849 clientX: clientX, 850 clientY: clientY, 851 x: clientX, 852 y: clientY, 853 movementX: moveX, 854 movementY: moveY, 855 offsetX: 0, 856 offsetY: 0, 857 layerX: 0, 858 layerY: 0 859 }); 860 } 861 return event; 862 }; 863 /** 864 * Determine if an event's registered handlers should be execute synchronously or asynchronously. 865 * 866 * @returns {boolean} 867 * @private 868 */ 869 var _shouldPerformAsync = function(event) { 870 var eventType = event && typeof event.type === "string" && event.type || ""; 871 return !/^(?:(?:before)?copy|destroy)$/.test(eventType); 872 }; 873 /** 874 * Control if a callback should be executed asynchronously or not. 875 * 876 * @returns `undefined` 877 * @private 878 */ 256 trustedOriginsExpanded.push.apply(trustedOriginsExpanded, [ domain, "//" + domain, window.location.protocol + "//" + domain ]); 257 } 258 } 259 } 260 if (trustedOriginsExpanded.length) { 261 str.push("trustedOrigins=" + encodeURIComponent(trustedOriginsExpanded.join(","))); 262 } 263 if (typeof options.jsModuleId === "string" && options.jsModuleId) { 264 str.push("jsModuleId=" + encodeURIComponent(options.jsModuleId)); 265 } 266 return str.join("&"); 267 }; 268 var _inArray = function(elem, array, fromIndex) { 269 if (typeof array.indexOf === "function") { 270 return array.indexOf(elem, fromIndex); 271 } 272 var i, len = array.length; 273 if (typeof fromIndex === "undefined") { 274 fromIndex = 0; 275 } else if (fromIndex < 0) { 276 fromIndex = len + fromIndex; 277 } 278 for (i = fromIndex; i < len; i++) { 279 if (array.hasOwnProperty(i) && array[i] === elem) { 280 return i; 281 } 282 } 283 return -1; 284 }; 285 var _prepClip = function(elements) { 286 if (typeof elements === "string") throw new TypeError("ZeroClipboard doesn't accept query strings."); 287 if (!elements.length) return [ elements ]; 288 return elements; 289 }; 879 290 var _dispatchCallback = function(func, context, args, async) { 880 291 if (async) { 881 _setTimeout(function() {292 window.setTimeout(function() { 882 293 func.apply(context, args); 883 294 }, 0); … … 886 297 } 887 298 }; 888 /** 889 * Handle the actual dispatching of events to client instances. 890 * 891 * @returns `undefined` 892 * @private 893 */ 894 var _dispatchCallbacks = function(event) { 895 if (!(typeof event === "object" && event && event.type)) { 896 return; 897 } 898 var async = _shouldPerformAsync(event); 899 var wildcardTypeHandlers = _handlers["*"] || []; 900 var specificTypeHandlers = _handlers[event.type] || []; 901 var handlers = wildcardTypeHandlers.concat(specificTypeHandlers); 902 if (handlers && handlers.length) { 903 var i, len, func, context, eventCopy, originalContext = this; 904 for (i = 0, len = handlers.length; i < len; i++) { 905 func = handlers[i]; 906 context = originalContext; 907 if (typeof func === "string" && typeof _window[func] === "function") { 908 func = _window[func]; 909 } 910 if (typeof func === "object" && func && typeof func.handleEvent === "function") { 911 context = func; 912 func = func.handleEvent; 913 } 914 if (typeof func === "function") { 915 eventCopy = _extend({}, event); 916 _dispatchCallback(func, context, [ eventCopy ], async); 917 } 918 } 919 } 920 return this; 921 }; 922 /** 923 * Check an `error` event's `name` property to see if Flash has 924 * already loaded, which rules out possible `iframe` sandboxing. 925 * @private 926 */ 927 var _getSandboxStatusFromErrorEvent = function(event) { 928 var isSandboxed = null; 929 if (_pageIsFramed === false || event && event.type === "error" && event.name && _errorsThatOnlyOccurAfterFlashLoads.indexOf(event.name) !== -1) { 930 isSandboxed = false; 931 } 932 return isSandboxed; 933 }; 934 /** 935 * Preprocess any special behaviors, reactions, or state changes after receiving this event. 936 * Executes only once per event emitted, NOT once per client. 937 * @private 938 */ 939 var _preprocessEvent = function(event) { 940 var element = event.target || _currentElement || null; 941 var sourceIsSwf = event._source === "swf"; 942 delete event._source; 943 switch (event.type) { 944 case "error": 945 var isSandboxed = event.name === "flash-sandboxed" || _getSandboxStatusFromErrorEvent(event); 946 if (typeof isSandboxed === "boolean") { 947 _flashState.sandboxed = isSandboxed; 948 } 949 if (_flashStateErrorNames.indexOf(event.name) !== -1) { 950 _extend(_flashState, { 951 disabled: event.name === "flash-disabled", 952 outdated: event.name === "flash-outdated", 953 unavailable: event.name === "flash-unavailable", 954 degraded: event.name === "flash-degraded", 955 deactivated: event.name === "flash-deactivated", 956 overdue: event.name === "flash-overdue", 957 ready: false 958 }); 959 } else if (event.name === "version-mismatch") { 960 _zcSwfVersion = event.swfVersion; 961 _extend(_flashState, { 962 disabled: false, 963 outdated: false, 964 unavailable: false, 965 degraded: false, 966 deactivated: false, 967 overdue: false, 968 ready: false 969 }); 970 } 971 _clearTimeoutsAndPolling(); 972 break; 973 974 case "ready": 975 _zcSwfVersion = event.swfVersion; 976 var wasDeactivated = _flashState.deactivated === true; 977 _extend(_flashState, { 978 disabled: false, 979 outdated: false, 980 sandboxed: false, 981 unavailable: false, 982 degraded: false, 983 deactivated: false, 984 overdue: wasDeactivated, 985 ready: !wasDeactivated 986 }); 987 _clearTimeoutsAndPolling(); 988 break; 989 990 case "beforecopy": 991 _copyTarget = element; 992 break; 993 994 case "copy": 995 var textContent, htmlContent, targetEl = event.relatedTarget; 996 if (!(_clipData["text/html"] || _clipData["text/plain"]) && targetEl && (htmlContent = targetEl.value || targetEl.outerHTML || targetEl.innerHTML) && (textContent = targetEl.value || targetEl.textContent || targetEl.innerText)) { 997 event.clipboardData.clearData(); 998 event.clipboardData.setData("text/plain", textContent); 999 if (htmlContent !== textContent) { 1000 event.clipboardData.setData("text/html", htmlContent); 1001 } 1002 } else if (!_clipData["text/plain"] && event.target && (textContent = event.target.getAttribute("data-clipboard-text"))) { 1003 event.clipboardData.clearData(); 1004 event.clipboardData.setData("text/plain", textContent); 1005 } 1006 break; 1007 1008 case "aftercopy": 1009 _queueEmitClipboardErrors(event); 1010 ZeroClipboard.clearData(); 1011 if (element && element !== _safeActiveElement() && element.focus) { 1012 element.focus(); 1013 } 1014 break; 1015 1016 case "_mouseover": 1017 ZeroClipboard.focus(element); 1018 if (_globalConfig.bubbleEvents === true && sourceIsSwf) { 1019 if (element && element !== event.relatedTarget && !_containedBy(event.relatedTarget, element)) { 1020 _fireMouseEvent(_extend({}, event, { 1021 type: "mouseenter", 1022 bubbles: false, 1023 cancelable: false 1024 })); 1025 } 1026 _fireMouseEvent(_extend({}, event, { 1027 type: "mouseover" 1028 })); 1029 } 1030 break; 1031 1032 case "_mouseout": 1033 ZeroClipboard.blur(); 1034 if (_globalConfig.bubbleEvents === true && sourceIsSwf) { 1035 if (element && element !== event.relatedTarget && !_containedBy(event.relatedTarget, element)) { 1036 _fireMouseEvent(_extend({}, event, { 1037 type: "mouseleave", 1038 bubbles: false, 1039 cancelable: false 1040 })); 1041 } 1042 _fireMouseEvent(_extend({}, event, { 1043 type: "mouseout" 1044 })); 1045 } 1046 break; 1047 1048 case "_mousedown": 1049 _addClass(element, _globalConfig.activeClass); 1050 if (_globalConfig.bubbleEvents === true && sourceIsSwf) { 1051 _fireMouseEvent(_extend({}, event, { 1052 type: event.type.slice(1) 1053 })); 1054 } 1055 break; 1056 1057 case "_mouseup": 1058 _removeClass(element, _globalConfig.activeClass); 1059 if (_globalConfig.bubbleEvents === true && sourceIsSwf) { 1060 _fireMouseEvent(_extend({}, event, { 1061 type: event.type.slice(1) 1062 })); 1063 } 1064 break; 1065 1066 case "_click": 1067 _copyTarget = null; 1068 if (_globalConfig.bubbleEvents === true && sourceIsSwf) { 1069 _fireMouseEvent(_extend({}, event, { 1070 type: event.type.slice(1) 1071 })); 1072 } 1073 break; 1074 1075 case "_mousemove": 1076 if (_globalConfig.bubbleEvents === true && sourceIsSwf) { 1077 _fireMouseEvent(_extend({}, event, { 1078 type: event.type.slice(1) 1079 })); 1080 } 1081 break; 1082 } 1083 if (/^_(?:click|mouse(?:over|out|down|up|move))$/.test(event.type)) { 1084 return true; 1085 } 1086 }; 1087 /** 1088 * Check an "aftercopy" event for clipboard errors and emit a corresponding "error" event. 1089 * @private 1090 */ 1091 var _queueEmitClipboardErrors = function(aftercopyEvent) { 1092 if (aftercopyEvent.errors && aftercopyEvent.errors.length > 0) { 1093 var errorEvent = _deepCopy(aftercopyEvent); 1094 _extend(errorEvent, { 1095 type: "error", 1096 name: "clipboard-error" 1097 }); 1098 delete errorEvent.success; 1099 _setTimeout(function() { 1100 ZeroClipboard.emit(errorEvent); 1101 }, 0); 1102 } 1103 }; 1104 /** 1105 * Dispatch a synthetic MouseEvent. 1106 * 1107 * @returns `undefined` 1108 * @private 1109 */ 1110 var _fireMouseEvent = function(event) { 1111 if (!(event && typeof event.type === "string" && event)) { 1112 return; 1113 } 1114 var e, target = event.target || null, doc = target && target.ownerDocument || _document, defaults = { 1115 view: doc.defaultView || _window, 1116 canBubble: true, 1117 cancelable: true, 1118 detail: event.type === "click" ? 1 : 0, 1119 button: typeof event.which === "number" ? event.which - 1 : typeof event.button === "number" ? event.button : doc.createEvent ? 0 : 1 1120 }, args = _extend(defaults, event); 1121 if (!target) { 1122 return; 1123 } 1124 if (doc.createEvent && target.dispatchEvent) { 1125 args = [ args.type, args.canBubble, args.cancelable, args.view, args.detail, args.screenX, args.screenY, args.clientX, args.clientY, args.ctrlKey, args.altKey, args.shiftKey, args.metaKey, args.button, args.relatedTarget ]; 1126 e = doc.createEvent("MouseEvents"); 1127 if (e.initMouseEvent) { 1128 e.initMouseEvent.apply(e, args); 1129 e._source = "js"; 1130 target.dispatchEvent(e); 1131 } 1132 } 1133 }; 1134 /** 1135 * Continuously poll the DOM until either: 1136 * (a) the fallback content becomes visible, or 1137 * (b) we receive an event from SWF (handled elsewhere) 1138 * 1139 * IMPORTANT: 1140 * This is NOT a necessary check but it can result in significantly faster 1141 * detection of bad `swfPath` configuration and/or network/server issues [in 1142 * supported browsers] than waiting for the entire `flashLoadTimeout` duration 1143 * to elapse before detecting that the SWF cannot be loaded. The detection 1144 * duration can be anywhere from 10-30 times faster [in supported browsers] by 1145 * using this approach. 1146 * 1147 * @returns `undefined` 1148 * @private 1149 */ 1150 var _watchForSwfFallbackContent = function() { 1151 var maxWait = _globalConfig.flashLoadTimeout; 1152 if (typeof maxWait === "number" && maxWait >= 0) { 1153 var pollWait = Math.min(1e3, maxWait / 10); 1154 var fallbackContentId = _globalConfig.swfObjectId + "_fallbackContent"; 1155 _swfFallbackCheckInterval = _setInterval(function() { 1156 var el = _document.getElementById(fallbackContentId); 1157 if (_isElementVisible(el)) { 1158 _clearTimeoutsAndPolling(); 1159 _flashState.deactivated = null; 1160 ZeroClipboard.emit({ 1161 type: "error", 1162 name: "swf-not-found" 1163 }); 1164 } 1165 }, pollWait); 1166 } 1167 }; 1168 /** 1169 * Create the HTML bridge element to embed the Flash object into. 1170 * @private 1171 */ 1172 var _createHtmlBridge = function() { 1173 var container = _document.createElement("div"); 1174 container.id = _globalConfig.containerId; 1175 container.className = _globalConfig.containerClass; 1176 container.style.position = "absolute"; 1177 container.style.left = "0px"; 1178 container.style.top = "-9999px"; 1179 container.style.width = "1px"; 1180 container.style.height = "1px"; 1181 container.style.zIndex = "" + _getSafeZIndex(_globalConfig.zIndex); 1182 return container; 1183 }; 1184 /** 1185 * Get the HTML element container that wraps the Flash bridge object/element. 1186 * @private 1187 */ 1188 var _getHtmlBridge = function(flashBridge) { 1189 var htmlBridge = flashBridge && flashBridge.parentNode; 1190 while (htmlBridge && htmlBridge.nodeName === "OBJECT" && htmlBridge.parentNode) { 1191 htmlBridge = htmlBridge.parentNode; 1192 } 1193 return htmlBridge || null; 1194 }; 1195 /** 1196 * Create the SWF object. 1197 * 1198 * @returns The SWF object reference. 1199 * @private 1200 */ 1201 var _embedSwf = function() { 1202 var len, flashBridge = _flashState.bridge, container = _getHtmlBridge(flashBridge); 1203 if (!flashBridge) { 1204 var allowScriptAccess = _determineScriptAccess(_window.location.host, _globalConfig); 1205 var allowNetworking = allowScriptAccess === "never" ? "none" : "all"; 1206 var flashvars = _vars(_extend({ 1207 jsVersion: ZeroClipboard.version 1208 }, _globalConfig)); 1209 var swfUrl = _globalConfig.swfPath + _cacheBust(_globalConfig.swfPath, _globalConfig); 1210 container = _createHtmlBridge(); 1211 var divToBeReplaced = _document.createElement("div"); 1212 container.appendChild(divToBeReplaced); 1213 _document.body.appendChild(container); 1214 var tmpDiv = _document.createElement("div"); 1215 var usingActiveX = _flashState.pluginType === "activex"; 1216 tmpDiv.innerHTML = '<object id="' + _globalConfig.swfObjectId + '" name="' + _globalConfig.swfObjectId + '" ' + 'width="100%" height="100%" ' + (usingActiveX ? 'classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"' : 'type="application/x-shockwave-flash" data="' + swfUrl + '"') + ">" + (usingActiveX ? '<param name="movie" value="' + swfUrl + '"/>' : "") + '<param name="allowScriptAccess" value="' + allowScriptAccess + '"/>' + '<param name="allowNetworking" value="' + allowNetworking + '"/>' + '<param name="menu" value="false"/>' + '<param name="wmode" value="transparent"/>' + '<param name="flashvars" value="' + flashvars + '"/>' + '<div id="' + _globalConfig.swfObjectId + '_fallbackContent"> </div>' + "</object>"; 1217 flashBridge = tmpDiv.firstChild; 1218 tmpDiv = null; 1219 _unwrap(flashBridge).ZeroClipboard = ZeroClipboard; 1220 container.replaceChild(flashBridge, divToBeReplaced); 1221 _watchForSwfFallbackContent(); 1222 } 1223 if (!flashBridge) { 1224 flashBridge = _document[_globalConfig.swfObjectId]; 1225 if (flashBridge && (len = flashBridge.length)) { 1226 flashBridge = flashBridge[len - 1]; 1227 } 1228 if (!flashBridge && container) { 1229 flashBridge = container.firstChild; 1230 } 1231 } 1232 _flashState.bridge = flashBridge || null; 1233 return flashBridge; 1234 }; 1235 /** 1236 * Destroy the SWF object. 1237 * @private 1238 */ 1239 var _unembedSwf = function() { 1240 var flashBridge = _flashState.bridge; 1241 if (flashBridge) { 1242 var htmlBridge = _getHtmlBridge(flashBridge); 1243 if (htmlBridge) { 1244 if (_flashState.pluginType === "activex" && "readyState" in flashBridge) { 1245 flashBridge.style.display = "none"; 1246 (function removeSwfFromIE() { 1247 if (flashBridge.readyState === 4) { 1248 for (var prop in flashBridge) { 1249 if (typeof flashBridge[prop] === "function") { 1250 flashBridge[prop] = null; 1251 } 1252 } 1253 if (flashBridge.parentNode) { 1254 flashBridge.parentNode.removeChild(flashBridge); 1255 } 1256 if (htmlBridge.parentNode) { 1257 htmlBridge.parentNode.removeChild(htmlBridge); 1258 } 1259 } else { 1260 _setTimeout(removeSwfFromIE, 10); 299 var _getSafeZIndex = function(val) { 300 var zIndex, tmp; 301 if (val) { 302 if (typeof val === "number" && val > 0) { 303 zIndex = val; 304 } else if (typeof val === "string" && (tmp = parseInt(val, 10)) && !isNaN(tmp) && tmp > 0) { 305 zIndex = tmp; 306 } 307 } 308 if (!zIndex) { 309 if (typeof _globalConfig.zIndex === "number" && _globalConfig.zIndex > 0) { 310 zIndex = _globalConfig.zIndex; 311 } else if (typeof _globalConfig.zIndex === "string" && (tmp = parseInt(_globalConfig.zIndex, 10)) && !isNaN(tmp) && tmp > 0) { 312 zIndex = tmp; 313 } 314 } 315 return zIndex || 0; 316 }; 317 var _deprecationWarning = function(deprecatedApiName, debugEnabled) { 318 if (deprecatedApiName && debugEnabled !== false && typeof console !== "undefined" && console && (console.warn || console.log)) { 319 var deprecationWarning = "`" + deprecatedApiName + "` is deprecated. See docs for more info:\n" + " https://github.com/zeroclipboard/zeroclipboard/blob/master/docs/instructions.md#deprecations"; 320 if (console.warn) { 321 console.warn(deprecationWarning); 322 } else { 323 console.log(deprecationWarning); 324 } 325 } 326 }; 327 var _extend = function() { 328 var i, len, arg, prop, src, copy, target = arguments[0] || {}; 329 for (i = 1, len = arguments.length; i < len; i++) { 330 if ((arg = arguments[i]) != null) { 331 for (prop in arg) { 332 if (arg.hasOwnProperty(prop)) { 333 src = target[prop]; 334 copy = arg[prop]; 335 if (target === copy) { 336 continue; 1261 337 } 1262 })(); 1263 } else { 1264 if (flashBridge.parentNode) { 1265 flashBridge.parentNode.removeChild(flashBridge); 1266 } 1267 if (htmlBridge.parentNode) { 1268 htmlBridge.parentNode.removeChild(htmlBridge); 1269 } 1270 } 1271 } 1272 _clearTimeoutsAndPolling(); 1273 _flashState.ready = null; 1274 _flashState.bridge = null; 1275 _flashState.deactivated = null; 1276 _zcSwfVersion = undefined; 1277 } 1278 }; 1279 /** 1280 * Map the data format names of the "clipData" to Flash-friendly names. 1281 * 1282 * @returns A new transformed object. 1283 * @private 1284 */ 1285 var _mapClipDataToFlash = function(clipData) { 1286 var newClipData = {}, formatMap = {}; 1287 if (!(typeof clipData === "object" && clipData)) { 1288 return; 1289 } 1290 for (var dataFormat in clipData) { 1291 if (dataFormat && _hasOwn.call(clipData, dataFormat) && typeof clipData[dataFormat] === "string" && clipData[dataFormat]) { 1292 switch (dataFormat.toLowerCase()) { 1293 case "text/plain": 1294 case "text": 1295 case "air:text": 1296 case "flash:text": 1297 newClipData.text = clipData[dataFormat]; 1298 formatMap.text = dataFormat; 1299 break; 1300 1301 case "text/html": 1302 case "html": 1303 case "air:html": 1304 case "flash:html": 1305 newClipData.html = clipData[dataFormat]; 1306 formatMap.html = dataFormat; 1307 break; 1308 1309 case "application/rtf": 1310 case "text/rtf": 1311 case "rtf": 1312 case "richtext": 1313 case "air:rtf": 1314 case "flash:rtf": 1315 newClipData.rtf = clipData[dataFormat]; 1316 formatMap.rtf = dataFormat; 1317 break; 1318 1319 default: 1320 break; 1321 } 1322 } 1323 } 1324 return { 1325 data: newClipData, 1326 formatMap: formatMap 1327 }; 1328 }; 1329 /** 1330 * Map the data format names from Flash-friendly names back to their original "clipData" names (via a format mapping). 1331 * 1332 * @returns A new transformed object. 1333 * @private 1334 */ 1335 var _mapClipResultsFromFlash = function(clipResults, formatMap) { 1336 if (!(typeof clipResults === "object" && clipResults && typeof formatMap === "object" && formatMap)) { 1337 return clipResults; 1338 } 1339 var newResults = {}; 1340 for (var prop in clipResults) { 1341 if (_hasOwn.call(clipResults, prop)) { 1342 if (prop === "errors") { 1343 newResults[prop] = clipResults[prop] ? clipResults[prop].slice() : []; 1344 for (var i = 0, len = newResults[prop].length; i < len; i++) { 1345 newResults[prop][i].format = formatMap[newResults[prop][i].format]; 1346 } 1347 } else if (prop !== "success" && prop !== "data") { 1348 newResults[prop] = clipResults[prop]; 1349 } else { 1350 newResults[prop] = {}; 1351 var tmpHash = clipResults[prop]; 1352 for (var dataFormat in tmpHash) { 1353 if (dataFormat && _hasOwn.call(tmpHash, dataFormat) && _hasOwn.call(formatMap, dataFormat)) { 1354 newResults[prop][formatMap[dataFormat]] = tmpHash[dataFormat]; 338 if (copy !== undefined) { 339 target[prop] = copy; 1355 340 } 1356 341 } … … 1358 343 } 1359 344 } 1360 return newResults; 1361 }; 1362 /** 1363 * Will look at a path, and will create a "?noCache={time}" or "&noCache={time}" 1364 * query param string to return. Does NOT append that string to the original path. 1365 * This is useful because ExternalInterface often breaks when a Flash SWF is cached. 1366 * 1367 * @returns The `noCache` query param with necessary "?"/"&" prefix. 1368 * @private 1369 */ 1370 var _cacheBust = function(path, options) { 1371 var cacheBust = options == null || options && options.cacheBust === true; 1372 if (cacheBust) { 1373 return (path.indexOf("?") === -1 ? "?" : "&") + "noCache=" + _now(); 1374 } else { 1375 return ""; 1376 } 1377 }; 1378 /** 1379 * Creates a query string for the FlashVars param. 1380 * Does NOT include the cache-busting query param. 1381 * 1382 * @returns FlashVars query string 1383 * @private 1384 */ 1385 var _vars = function(options) { 1386 var i, len, domain, domains, str = "", trustedOriginsExpanded = []; 1387 if (options.trustedDomains) { 1388 if (typeof options.trustedDomains === "string") { 1389 domains = [ options.trustedDomains ]; 1390 } else if (typeof options.trustedDomains === "object" && "length" in options.trustedDomains) { 1391 domains = options.trustedDomains; 1392 } 1393 } 1394 if (domains && domains.length) { 1395 for (i = 0, len = domains.length; i < len; i++) { 1396 if (_hasOwn.call(domains, i) && domains[i] && typeof domains[i] === "string") { 1397 domain = _extractDomain(domains[i]); 1398 if (!domain) { 1399 continue; 1400 } 1401 if (domain === "*") { 1402 trustedOriginsExpanded.length = 0; 1403 trustedOriginsExpanded.push(domain); 1404 break; 1405 } 1406 trustedOriginsExpanded.push.apply(trustedOriginsExpanded, [ domain, "//" + domain, _window.location.protocol + "//" + domain ]); 1407 } 1408 } 1409 } 1410 if (trustedOriginsExpanded.length) { 1411 str += "trustedOrigins=" + _encodeURIComponent(trustedOriginsExpanded.join(",")); 1412 } 1413 if (options.forceEnhancedClipboard === true) { 1414 str += (str ? "&" : "") + "forceEnhancedClipboard=true"; 1415 } 1416 if (typeof options.swfObjectId === "string" && options.swfObjectId) { 1417 str += (str ? "&" : "") + "swfObjectId=" + _encodeURIComponent(options.swfObjectId); 1418 } 1419 if (typeof options.jsVersion === "string" && options.jsVersion) { 1420 str += (str ? "&" : "") + "jsVersion=" + _encodeURIComponent(options.jsVersion); 1421 } 1422 return str; 1423 }; 1424 /** 1425 * Extract the domain (e.g. "github.com") from an origin (e.g. "https://github.com") or 1426 * URL (e.g. "https://github.com/zeroclipboard/zeroclipboard/"). 1427 * 1428 * @returns the domain 1429 * @private 1430 */ 345 return target; 346 }; 1431 347 var _extractDomain = function(originOrUrl) { 1432 348 if (originOrUrl == null || originOrUrl === "") { … … 1446 362 return originOrUrl || null; 1447 363 }; 1448 /**1449 * Set `allowScriptAccess` based on `trustedDomains` and `window.location.host` vs. `swfPath`.1450 *1451 * @returns The appropriate script access level.1452 * @private1453 */1454 364 var _determineScriptAccess = function() { 1455 var _extractAllDomains = function(origins) { 1456 var i, len, tmp, resultsArray = []; 1457 if (typeof origins === "string") { 1458 origins = [ origins ]; 1459 } 1460 if (!(typeof origins === "object" && origins && typeof origins.length === "number")) { 1461 return resultsArray; 1462 } 1463 for (i = 0, len = origins.length; i < len; i++) { 1464 if (_hasOwn.call(origins, i) && (tmp = _extractDomain(origins[i]))) { 1465 if (tmp === "*") { 1466 resultsArray.length = 0; 1467 resultsArray.push("*"); 1468 break; 1469 } 1470 if (resultsArray.indexOf(tmp) === -1) { 1471 resultsArray.push(tmp); 1472 } 1473 } 1474 } 1475 return resultsArray; 365 var _extractAllDomains = function(origins, resultsArray) { 366 var i, len, tmp; 367 if (origins != null && resultsArray[0] !== "*") { 368 if (typeof origins === "string") { 369 origins = [ origins ]; 370 } 371 if (typeof origins === "object" && "length" in origins) { 372 for (i = 0, len = origins.length; i < len; i++) { 373 if (origins.hasOwnProperty(i)) { 374 tmp = _extractDomain(origins[i]); 375 if (tmp) { 376 if (tmp === "*") { 377 resultsArray.length = 0; 378 resultsArray.push("*"); 379 break; 380 } 381 if (_inArray(tmp, resultsArray) === -1) { 382 resultsArray.push(tmp); 383 } 384 } 385 } 386 } 387 } 388 } 389 }; 390 var _accessLevelLookup = { 391 always: "always", 392 samedomain: "sameDomain", 393 never: "never" 1476 394 }; 1477 395 return function(currentDomain, configOptions) { 1478 var swfDomain = _extractDomain(configOptions.swfPath); 396 var asaLower, allowScriptAccess = configOptions.allowScriptAccess; 397 if (typeof allowScriptAccess === "string" && (asaLower = allowScriptAccess.toLowerCase()) && /^always|samedomain|never$/.test(asaLower)) { 398 return _accessLevelLookup[asaLower]; 399 } 400 var swfDomain = _extractDomain(configOptions.moviePath); 1479 401 if (swfDomain === null) { 1480 402 swfDomain = currentDomain; 1481 403 } 1482 var trustedDomains = _extractAllDomains(configOptions.trustedDomains); 404 var trustedDomains = []; 405 _extractAllDomains(configOptions.trustedOrigins, trustedDomains); 406 _extractAllDomains(configOptions.trustedDomains, trustedDomains); 1483 407 var len = trustedDomains.length; 1484 408 if (len > 0) { … … 1486 410 return "always"; 1487 411 } 1488 if ( trustedDomains.indexOf(currentDomain) !== -1) {412 if (_inArray(currentDomain, trustedDomains) !== -1) { 1489 413 if (len === 1 && currentDomain === swfDomain) { 1490 414 return "sameDomain"; … … 1496 420 }; 1497 421 }(); 1498 /** 1499 * Get the currently active/focused DOM element. 1500 * 1501 * @returns the currently active/focused element, or `null` 1502 * @private 1503 */ 422 var _objectKeys = function(obj) { 423 if (obj == null) { 424 return []; 425 } 426 if (Object.keys) { 427 return Object.keys(obj); 428 } 429 var keys = []; 430 for (var prop in obj) { 431 if (obj.hasOwnProperty(prop)) { 432 keys.push(prop); 433 } 434 } 435 return keys; 436 }; 437 var _deleteOwnProperties = function(obj) { 438 if (obj) { 439 for (var prop in obj) { 440 if (obj.hasOwnProperty(prop)) { 441 delete obj[prop]; 442 } 443 } 444 } 445 return obj; 446 }; 1504 447 var _safeActiveElement = function() { 1505 448 try { 1506 return _document.activeElement; 1507 } catch (err) { 1508 return null; 1509 } 1510 }; 1511 /** 1512 * Add a class to an element, if it doesn't already have it. 1513 * 1514 * @returns The element, with its new class added. 1515 * @private 1516 */ 1517 var _addClass = function(element, value) { 1518 var c, cl, className, classNames = []; 1519 if (typeof value === "string" && value) { 1520 classNames = value.split(/\s+/); 1521 } 1522 if (element && element.nodeType === 1 && classNames.length > 0) { 1523 if (element.classList) { 1524 for (c = 0, cl = classNames.length; c < cl; c++) { 1525 element.classList.add(classNames[c]); 1526 } 1527 } else if (element.hasOwnProperty("className")) { 1528 className = " " + element.className + " "; 1529 for (c = 0, cl = classNames.length; c < cl; c++) { 1530 if (className.indexOf(" " + classNames[c] + " ") === -1) { 1531 className += classNames[c] + " "; 1532 } 1533 } 1534 element.className = className.replace(/^\s+|\s+$/g, ""); 1535 } 1536 } 1537 return element; 1538 }; 1539 /** 1540 * Remove a class from an element, if it has it. 1541 * 1542 * @returns The element, with its class removed. 1543 * @private 1544 */ 1545 var _removeClass = function(element, value) { 1546 var c, cl, className, classNames = []; 1547 if (typeof value === "string" && value) { 1548 classNames = value.split(/\s+/); 1549 } 1550 if (element && element.nodeType === 1 && classNames.length > 0) { 1551 if (element.classList && element.classList.length > 0) { 1552 for (c = 0, cl = classNames.length; c < cl; c++) { 1553 element.classList.remove(classNames[c]); 1554 } 1555 } else if (element.className) { 1556 className = (" " + element.className + " ").replace(/[\r\n\t]/g, " "); 1557 for (c = 0, cl = classNames.length; c < cl; c++) { 1558 className = className.replace(" " + classNames[c] + " ", " "); 1559 } 1560 element.className = className.replace(/^\s+|\s+$/g, ""); 1561 } 1562 } 1563 return element; 1564 }; 1565 /** 1566 * Attempt to interpret the element's CSS styling. If `prop` is `"cursor"`, 1567 * then we assume that it should be a hand ("pointer") cursor if the element 1568 * is an anchor element ("a" tag). 1569 * 1570 * @returns The computed style property. 1571 * @private 1572 */ 1573 var _getStyle = function(el, prop) { 1574 var value = _getComputedStyle(el, null).getPropertyValue(prop); 1575 if (prop === "cursor") { 1576 if (!value || value === "auto") { 1577 if (el.nodeName === "A") { 1578 return "pointer"; 1579 } 1580 } 1581 } 1582 return value; 1583 }; 1584 /** 1585 * Get the absolutely positioned coordinates of a DOM element. 1586 * 1587 * @returns Object containing the element's position, width, and height. 1588 * @private 1589 */ 1590 var _getElementPosition = function(el) { 1591 var pos = { 1592 left: 0, 1593 top: 0, 1594 width: 0, 1595 height: 0 449 return document.activeElement; 450 } catch (err) {} 451 return null; 452 }; 453 var _detectFlashSupport = function() { 454 var hasFlash = false; 455 if (typeof flashState.disabled === "boolean") { 456 hasFlash = flashState.disabled === false; 457 } else { 458 if (typeof ActiveXObject === "function") { 459 try { 460 if (new ActiveXObject("ShockwaveFlash.ShockwaveFlash")) { 461 hasFlash = true; 462 } 463 } catch (error) {} 464 } 465 if (!hasFlash && navigator.mimeTypes["application/x-shockwave-flash"]) { 466 hasFlash = true; 467 } 468 } 469 return hasFlash; 470 }; 471 function _parseFlashVersion(flashVersion) { 472 return flashVersion.replace(/,/g, ".").replace(/[^0-9\.]/g, ""); 473 } 474 function _isFlashVersionSupported(flashVersion) { 475 return parseFloat(_parseFlashVersion(flashVersion)) >= 10; 476 } 477 var ZeroClipboard = function(elements, options) { 478 if (!(this instanceof ZeroClipboard)) { 479 return new ZeroClipboard(elements, options); 480 } 481 this.id = "" + clientIdCounter++; 482 _clientMeta[this.id] = { 483 instance: this, 484 elements: [], 485 handlers: {} 1596 486 }; 1597 if (el.getBoundingClientRect) { 1598 var elRect = el.getBoundingClientRect(); 1599 var pageXOffset = _window.pageXOffset; 1600 var pageYOffset = _window.pageYOffset; 1601 var leftBorderWidth = _document.documentElement.clientLeft || 0; 1602 var topBorderWidth = _document.documentElement.clientTop || 0; 1603 var leftBodyOffset = 0; 1604 var topBodyOffset = 0; 1605 if (_getStyle(_document.body, "position") === "relative") { 1606 var bodyRect = _document.body.getBoundingClientRect(); 1607 var htmlRect = _document.documentElement.getBoundingClientRect(); 1608 leftBodyOffset = bodyRect.left - htmlRect.left || 0; 1609 topBodyOffset = bodyRect.top - htmlRect.top || 0; 1610 } 1611 pos.left = elRect.left + pageXOffset - leftBorderWidth - leftBodyOffset; 1612 pos.top = elRect.top + pageYOffset - topBorderWidth - topBodyOffset; 1613 pos.width = "width" in elRect ? elRect.width : elRect.right - elRect.left; 1614 pos.height = "height" in elRect ? elRect.height : elRect.bottom - elRect.top; 1615 } 1616 return pos; 1617 }; 1618 /** 1619 * Determine is an element is visible somewhere within the document (page). 1620 * 1621 * @returns Boolean 1622 * @private 1623 */ 1624 var _isElementVisible = function(el) { 1625 if (!el) { 1626 return false; 1627 } 1628 var styles = _getComputedStyle(el, null); 1629 var hasCssHeight = _parseFloat(styles.height) > 0; 1630 var hasCssWidth = _parseFloat(styles.width) > 0; 1631 var hasCssTop = _parseFloat(styles.top) >= 0; 1632 var hasCssLeft = _parseFloat(styles.left) >= 0; 1633 var cssKnows = hasCssHeight && hasCssWidth && hasCssTop && hasCssLeft; 1634 var rect = cssKnows ? null : _getElementPosition(el); 1635 var isVisible = styles.display !== "none" && styles.visibility !== "collapse" && (cssKnows || !!rect && (hasCssHeight || rect.height > 0) && (hasCssWidth || rect.width > 0) && (hasCssTop || rect.top >= 0) && (hasCssLeft || rect.left >= 0)); 1636 return isVisible; 1637 }; 1638 /** 1639 * Clear all existing timeouts and interval polling delegates. 1640 * 1641 * @returns `undefined` 1642 * @private 1643 */ 1644 var _clearTimeoutsAndPolling = function() { 1645 _clearTimeout(_flashCheckTimeout); 1646 _flashCheckTimeout = 0; 1647 _clearInterval(_swfFallbackCheckInterval); 1648 _swfFallbackCheckInterval = 0; 1649 }; 1650 /** 1651 * Reposition the Flash object to cover the currently activated element. 1652 * 1653 * @returns `undefined` 1654 * @private 1655 */ 487 if (elements) { 488 this.clip(elements); 489 } 490 if (typeof options !== "undefined") { 491 _deprecationWarning("new ZeroClipboard(elements, options)", _globalConfig.debug); 492 ZeroClipboard.config(options); 493 } 494 this.options = ZeroClipboard.config(); 495 if (typeof flashState.disabled !== "boolean") { 496 flashState.disabled = !_detectFlashSupport(); 497 } 498 if (flashState.disabled === false && flashState.outdated !== true) { 499 if (flashState.bridge === null) { 500 flashState.outdated = false; 501 flashState.ready = false; 502 _bridge(); 503 } 504 } 505 }; 506 ZeroClipboard.prototype.setText = function(newText) { 507 if (newText && newText !== "") { 508 _clipData["text/plain"] = newText; 509 if (flashState.ready === true && flashState.bridge && typeof flashState.bridge.setText === "function") { 510 flashState.bridge.setText(newText); 511 } else { 512 flashState.ready = false; 513 } 514 } 515 return this; 516 }; 517 ZeroClipboard.prototype.setSize = function(width, height) { 518 if (flashState.ready === true && flashState.bridge && typeof flashState.bridge.setSize === "function") { 519 flashState.bridge.setSize(width, height); 520 } else { 521 flashState.ready = false; 522 } 523 return this; 524 }; 525 var _setHandCursor = function(enabled) { 526 if (flashState.ready === true && flashState.bridge && typeof flashState.bridge.setHandCursor === "function") { 527 flashState.bridge.setHandCursor(enabled); 528 } else { 529 flashState.ready = false; 530 } 531 }; 532 ZeroClipboard.prototype.destroy = function() { 533 this.unclip(); 534 this.off(); 535 delete _clientMeta[this.id]; 536 }; 537 var _getAllClients = function() { 538 var i, len, client, clients = [], clientIds = _objectKeys(_clientMeta); 539 for (i = 0, len = clientIds.length; i < len; i++) { 540 client = _clientMeta[clientIds[i]].instance; 541 if (client && client instanceof ZeroClipboard) { 542 clients.push(client); 543 } 544 } 545 return clients; 546 }; 547 ZeroClipboard.version = "1.3.5"; 548 var _globalConfig = { 549 swfPath: _swfPath, 550 trustedDomains: window.location.host ? [ window.location.host ] : [], 551 cacheBust: true, 552 forceHandCursor: false, 553 zIndex: 999999999, 554 debug: true, 555 title: null, 556 autoActivate: true 557 }; 558 ZeroClipboard.config = function(options) { 559 if (typeof options === "object" && options !== null) { 560 _extend(_globalConfig, options); 561 } 562 if (typeof options === "string" && options) { 563 if (_globalConfig.hasOwnProperty(options)) { 564 return _globalConfig[options]; 565 } 566 return; 567 } 568 var copy = {}; 569 for (var prop in _globalConfig) { 570 if (_globalConfig.hasOwnProperty(prop)) { 571 if (typeof _globalConfig[prop] === "object" && _globalConfig[prop] !== null) { 572 if ("length" in _globalConfig[prop]) { 573 copy[prop] = _globalConfig[prop].slice(0); 574 } else { 575 copy[prop] = _extend({}, _globalConfig[prop]); 576 } 577 } else { 578 copy[prop] = _globalConfig[prop]; 579 } 580 } 581 } 582 return copy; 583 }; 584 ZeroClipboard.destroy = function() { 585 ZeroClipboard.deactivate(); 586 for (var clientId in _clientMeta) { 587 if (_clientMeta.hasOwnProperty(clientId) && _clientMeta[clientId]) { 588 var client = _clientMeta[clientId].instance; 589 if (client && typeof client.destroy === "function") { 590 client.destroy(); 591 } 592 } 593 } 594 var htmlBridge = _getHtmlBridge(flashState.bridge); 595 if (htmlBridge && htmlBridge.parentNode) { 596 htmlBridge.parentNode.removeChild(htmlBridge); 597 flashState.ready = null; 598 flashState.bridge = null; 599 } 600 }; 601 ZeroClipboard.activate = function(element) { 602 if (currentElement) { 603 _removeClass(currentElement, _globalConfig.hoverClass); 604 _removeClass(currentElement, _globalConfig.activeClass); 605 } 606 currentElement = element; 607 _addClass(element, _globalConfig.hoverClass); 608 _reposition(); 609 var newTitle = _globalConfig.title || element.getAttribute("title"); 610 if (newTitle) { 611 var htmlBridge = _getHtmlBridge(flashState.bridge); 612 if (htmlBridge) { 613 htmlBridge.setAttribute("title", newTitle); 614 } 615 } 616 var useHandCursor = _globalConfig.forceHandCursor === true || _getStyle(element, "cursor") === "pointer"; 617 _setHandCursor(useHandCursor); 618 }; 619 ZeroClipboard.deactivate = function() { 620 var htmlBridge = _getHtmlBridge(flashState.bridge); 621 if (htmlBridge) { 622 htmlBridge.style.left = "0px"; 623 htmlBridge.style.top = "-9999px"; 624 htmlBridge.removeAttribute("title"); 625 } 626 if (currentElement) { 627 _removeClass(currentElement, _globalConfig.hoverClass); 628 _removeClass(currentElement, _globalConfig.activeClass); 629 currentElement = null; 630 } 631 }; 632 var _bridge = function() { 633 var flashBridge, len; 634 var container = document.getElementById("global-zeroclipboard-html-bridge"); 635 if (!container) { 636 var opts = ZeroClipboard.config(); 637 opts.jsModuleId = typeof _amdModuleId === "string" && _amdModuleId || typeof _cjsModuleId === "string" && _cjsModuleId || null; 638 var allowScriptAccess = _determineScriptAccess(window.location.host, _globalConfig); 639 var flashvars = _vars(opts); 640 var swfUrl = _globalConfig.moviePath + _cacheBust(_globalConfig.moviePath, _globalConfig); 641 var html = ' <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" id="global-zeroclipboard-flash-bridge" width="100%" height="100%"> <param name="movie" value="' + swfUrl + '"/> <param name="allowScriptAccess" value="' + allowScriptAccess + '"/> <param name="scale" value="exactfit"/> <param name="loop" value="false"/> <param name="menu" value="false"/> <param name="quality" value="best" /> <param name="bgcolor" value="#ffffff"/> <param name="wmode" value="transparent"/> <param name="flashvars" value="' + flashvars + '"/> <embed src="' + swfUrl + '" loop="false" menu="false" quality="best" bgcolor="#ffffff" width="100%" height="100%" name="global-zeroclipboard-flash-bridge" allowScriptAccess="' + allowScriptAccess + '" allowFullScreen="false" type="application/x-shockwave-flash" wmode="transparent" pluginspage="http://www.macromedia.com/go/getflashplayer" flashvars="' + flashvars + '" scale="exactfit"> </embed> </object>'; 642 container = document.createElement("div"); 643 container.id = "global-zeroclipboard-html-bridge"; 644 container.setAttribute("class", "global-zeroclipboard-container"); 645 container.style.position = "absolute"; 646 container.style.left = "0px"; 647 container.style.top = "-9999px"; 648 container.style.width = "15px"; 649 container.style.height = "15px"; 650 container.style.zIndex = "" + _getSafeZIndex(_globalConfig.zIndex); 651 document.body.appendChild(container); 652 container.innerHTML = html; 653 } 654 flashBridge = document["global-zeroclipboard-flash-bridge"]; 655 if (flashBridge && (len = flashBridge.length)) { 656 flashBridge = flashBridge[len - 1]; 657 } 658 flashState.bridge = flashBridge || container.children[0].lastElementChild; 659 }; 660 var _getHtmlBridge = function(flashBridge) { 661 var isFlashElement = /^OBJECT|EMBED$/; 662 var htmlBridge = flashBridge && flashBridge.parentNode; 663 while (htmlBridge && isFlashElement.test(htmlBridge.nodeName) && htmlBridge.parentNode) { 664 htmlBridge = htmlBridge.parentNode; 665 } 666 return htmlBridge || null; 667 }; 1656 668 var _reposition = function() { 1657 var htmlBridge; 1658 if (_currentElement && (htmlBridge = _getHtmlBridge(_flashState.bridge))) { 1659 var pos = _getElementPosition(_currentElement); 1660 _extend(htmlBridge.style, { 1661 width: pos.width + "px", 1662 height: pos.height + "px", 1663 top: pos.top + "px", 1664 left: pos.left + "px", 1665 zIndex: "" + _getSafeZIndex(_globalConfig.zIndex) 1666 }); 1667 } 1668 }; 1669 /** 1670 * Sends a signal to the Flash object to display the hand cursor if `true`. 1671 * 1672 * @returns `undefined` 1673 * @private 1674 */ 1675 var _setHandCursor = function(enabled) { 1676 if (_flashState.ready === true) { 1677 if (_flashState.bridge && typeof _flashState.bridge.setHandCursor === "function") { 1678 _flashState.bridge.setHandCursor(enabled); 669 if (currentElement) { 670 var pos = _getDOMObjectPosition(currentElement, _globalConfig.zIndex); 671 var htmlBridge = _getHtmlBridge(flashState.bridge); 672 if (htmlBridge) { 673 htmlBridge.style.top = pos.top + "px"; 674 htmlBridge.style.left = pos.left + "px"; 675 htmlBridge.style.width = pos.width + "px"; 676 htmlBridge.style.height = pos.height + "px"; 677 htmlBridge.style.zIndex = pos.zIndex + 1; 678 } 679 if (flashState.ready === true && flashState.bridge && typeof flashState.bridge.setSize === "function") { 680 flashState.bridge.setSize(pos.width, pos.height); 1679 681 } else { 1680 _flashState.ready = false; 1681 } 1682 } 1683 }; 1684 /** 1685 * Get a safe value for `zIndex` 1686 * 1687 * @returns an integer, or "auto" 1688 * @private 1689 */ 1690 var _getSafeZIndex = function(val) { 1691 if (/^(?:auto|inherit)$/.test(val)) { 1692 return val; 1693 } 1694 var zIndex; 1695 if (typeof val === "number" && !_isNaN(val)) { 1696 zIndex = val; 1697 } else if (typeof val === "string") { 1698 zIndex = _getSafeZIndex(_parseInt(val, 10)); 1699 } 1700 return typeof zIndex === "number" ? zIndex : "auto"; 1701 }; 1702 /** 1703 * Attempt to detect if ZeroClipboard is executing inside of a sandboxed iframe. 1704 * If it is, Flash Player cannot be used, so ZeroClipboard is dead in the water. 1705 * 1706 * @see {@link http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Dec/0002.html} 1707 * @see {@link https://github.com/zeroclipboard/zeroclipboard/issues/511} 1708 * @see {@link http://zeroclipboard.org/test-iframes.html} 1709 * 1710 * @returns `true` (is sandboxed), `false` (is not sandboxed), or `null` (uncertain) 1711 * @private 1712 */ 1713 var _detectSandbox = function(doNotReassessFlashSupport) { 1714 var effectiveScriptOrigin, frame, frameError, previousState = _flashState.sandboxed, isSandboxed = null; 1715 doNotReassessFlashSupport = doNotReassessFlashSupport === true; 1716 if (_pageIsFramed === false) { 1717 isSandboxed = false; 1718 } else { 1719 try { 1720 frame = window.frameElement || null; 1721 } catch (e) { 1722 frameError = { 1723 name: e.name, 1724 message: e.message 1725 }; 1726 } 1727 if (frame && frame.nodeType === 1 && frame.nodeName === "IFRAME") { 1728 try { 1729 isSandboxed = frame.hasAttribute("sandbox"); 1730 } catch (e) { 1731 isSandboxed = null; 1732 } 682 flashState.ready = false; 683 } 684 } 685 return this; 686 }; 687 ZeroClipboard.prototype.on = function(eventName, func) { 688 var i, len, events, added = {}, handlers = _clientMeta[this.id] && _clientMeta[this.id].handlers; 689 if (typeof eventName === "string" && eventName) { 690 events = eventName.toLowerCase().split(/\s+/); 691 } else if (typeof eventName === "object" && eventName && typeof func === "undefined") { 692 for (i in eventName) { 693 if (eventName.hasOwnProperty(i) && typeof i === "string" && i && typeof eventName[i] === "function") { 694 this.on(i, eventName[i]); 695 } 696 } 697 } 698 if (events && events.length) { 699 for (i = 0, len = events.length; i < len; i++) { 700 eventName = events[i].replace(/^on/, ""); 701 added[eventName] = true; 702 if (!handlers[eventName]) { 703 handlers[eventName] = []; 704 } 705 handlers[eventName].push(func); 706 } 707 if (added.noflash && flashState.disabled) { 708 _receiveEvent.call(this, "noflash", {}); 709 } 710 if (added.wrongflash && flashState.outdated) { 711 _receiveEvent.call(this, "wrongflash", { 712 flashVersion: flashState.version 713 }); 714 } 715 if (added.load && flashState.ready) { 716 _receiveEvent.call(this, "load", { 717 flashVersion: flashState.version 718 }); 719 } 720 } 721 return this; 722 }; 723 ZeroClipboard.prototype.off = function(eventName, func) { 724 var i, len, foundIndex, events, perEventHandlers, handlers = _clientMeta[this.id] && _clientMeta[this.id].handlers; 725 if (arguments.length === 0) { 726 events = _objectKeys(handlers); 727 } else if (typeof eventName === "string" && eventName) { 728 events = eventName.split(/\s+/); 729 } else if (typeof eventName === "object" && eventName && typeof func === "undefined") { 730 for (i in eventName) { 731 if (eventName.hasOwnProperty(i) && typeof i === "string" && i && typeof eventName[i] === "function") { 732 this.off(i, eventName[i]); 733 } 734 } 735 } 736 if (events && events.length) { 737 for (i = 0, len = events.length; i < len; i++) { 738 eventName = events[i].toLowerCase().replace(/^on/, ""); 739 perEventHandlers = handlers[eventName]; 740 if (perEventHandlers && perEventHandlers.length) { 741 if (func) { 742 foundIndex = _inArray(func, perEventHandlers); 743 while (foundIndex !== -1) { 744 perEventHandlers.splice(foundIndex, 1); 745 foundIndex = _inArray(func, perEventHandlers, foundIndex); 746 } 747 } else { 748 handlers[eventName].length = 0; 749 } 750 } 751 } 752 } 753 return this; 754 }; 755 ZeroClipboard.prototype.handlers = function(eventName) { 756 var prop, copy = null, handlers = _clientMeta[this.id] && _clientMeta[this.id].handlers; 757 if (handlers) { 758 if (typeof eventName === "string" && eventName) { 759 return handlers[eventName] ? handlers[eventName].slice(0) : null; 760 } 761 copy = {}; 762 for (prop in handlers) { 763 if (handlers.hasOwnProperty(prop) && handlers[prop]) { 764 copy[prop] = handlers[prop].slice(0); 765 } 766 } 767 } 768 return copy; 769 }; 770 var _dispatchClientCallbacks = function(eventName, context, args, async) { 771 var handlers = _clientMeta[this.id] && _clientMeta[this.id].handlers[eventName]; 772 if (handlers && handlers.length) { 773 var i, len, func, originalContext = context || this; 774 for (i = 0, len = handlers.length; i < len; i++) { 775 func = handlers[i]; 776 context = originalContext; 777 if (typeof func === "string" && typeof window[func] === "function") { 778 func = window[func]; 779 } 780 if (typeof func === "object" && func && typeof func.handleEvent === "function") { 781 context = func; 782 func = func.handleEvent; 783 } 784 if (typeof func === "function") { 785 _dispatchCallback(func, context, args, async); 786 } 787 } 788 } 789 return this; 790 }; 791 ZeroClipboard.prototype.clip = function(elements) { 792 elements = _prepClip(elements); 793 for (var i = 0; i < elements.length; i++) { 794 if (elements.hasOwnProperty(i) && elements[i] && elements[i].nodeType === 1) { 795 if (!elements[i].zcClippingId) { 796 elements[i].zcClippingId = "zcClippingId_" + elementIdCounter++; 797 _elementMeta[elements[i].zcClippingId] = [ this.id ]; 798 if (_globalConfig.autoActivate === true) { 799 _addEventHandler(elements[i], "mouseover", _elementMouseOver); 800 } 801 } else if (_inArray(this.id, _elementMeta[elements[i].zcClippingId]) === -1) { 802 _elementMeta[elements[i].zcClippingId].push(this.id); 803 } 804 var clippedElements = _clientMeta[this.id].elements; 805 if (_inArray(elements[i], clippedElements) === -1) { 806 clippedElements.push(elements[i]); 807 } 808 } 809 } 810 return this; 811 }; 812 ZeroClipboard.prototype.unclip = function(elements) { 813 var meta = _clientMeta[this.id]; 814 if (meta) { 815 var clippedElements = meta.elements; 816 var arrayIndex; 817 if (typeof elements === "undefined") { 818 elements = clippedElements.slice(0); 1733 819 } else { 1734 try { 1735 effectiveScriptOrigin = document.domain || null; 1736 } catch (e) { 1737 effectiveScriptOrigin = null; 1738 } 1739 if (effectiveScriptOrigin === null || frameError && frameError.name === "SecurityError" && /(^|[\s\(\[@])sandbox(es|ed|ing|[\s\.,!\)\]@]|$)/.test(frameError.message.toLowerCase())) { 1740 isSandboxed = true; 1741 } 1742 } 1743 } 1744 _flashState.sandboxed = isSandboxed; 1745 if (previousState !== isSandboxed && !doNotReassessFlashSupport) { 1746 _detectFlashSupport(_ActiveXObject); 1747 } 1748 return isSandboxed; 1749 }; 1750 /** 1751 * Detect the Flash Player status, version, and plugin type. 1752 * 1753 * @see {@link https://code.google.com/p/doctype-mirror/wiki/ArticleDetectFlash#The_code} 1754 * @see {@link http://stackoverflow.com/questions/12866060/detecting-pepper-ppapi-flash-with-javascript} 1755 * 1756 * @returns `undefined` 1757 * @private 1758 */ 1759 var _detectFlashSupport = function(ActiveXObject) { 1760 var plugin, ax, mimeType, hasFlash = false, isActiveX = false, isPPAPI = false, flashVersion = ""; 1761 /** 1762 * Derived from Apple's suggested sniffer. 1763 * @param {String} desc e.g. "Shockwave Flash 7.0 r61" 1764 * @returns {String} "7.0.61" 1765 * @private 1766 */ 1767 function parseFlashVersion(desc) { 1768 var matches = desc.match(/[\d]+/g); 1769 matches.length = 3; 1770 return matches.join("."); 1771 } 1772 function isPepperFlash(flashPlayerFileName) { 1773 return !!flashPlayerFileName && (flashPlayerFileName = flashPlayerFileName.toLowerCase()) && (/^(pepflashplayer\.dll|libpepflashplayer\.so|pepperflashplayer\.plugin)$/.test(flashPlayerFileName) || flashPlayerFileName.slice(-13) === "chrome.plugin"); 1774 } 1775 function inspectPlugin(plugin) { 1776 if (plugin) { 1777 hasFlash = true; 1778 if (plugin.version) { 1779 flashVersion = parseFlashVersion(plugin.version); 1780 } 1781 if (!flashVersion && plugin.description) { 1782 flashVersion = parseFlashVersion(plugin.description); 1783 } 1784 if (plugin.filename) { 1785 isPPAPI = isPepperFlash(plugin.filename); 1786 } 1787 } 1788 } 1789 if (_navigator.plugins && _navigator.plugins.length) { 1790 plugin = _navigator.plugins["Shockwave Flash"]; 1791 inspectPlugin(plugin); 1792 if (_navigator.plugins["Shockwave Flash 2.0"]) { 1793 hasFlash = true; 1794 flashVersion = "2.0.0.11"; 1795 } 1796 } else if (_navigator.mimeTypes && _navigator.mimeTypes.length) { 1797 mimeType = _navigator.mimeTypes["application/x-shockwave-flash"]; 1798 plugin = mimeType && mimeType.enabledPlugin; 1799 inspectPlugin(plugin); 1800 } else if (typeof ActiveXObject !== "undefined") { 1801 isActiveX = true; 1802 try { 1803 ax = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7"); 1804 hasFlash = true; 1805 flashVersion = parseFlashVersion(ax.GetVariable("$version")); 1806 } catch (e1) { 1807 try { 1808 ax = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6"); 1809 hasFlash = true; 1810 flashVersion = "6.0.21"; 1811 } catch (e2) { 1812 try { 1813 ax = new ActiveXObject("ShockwaveFlash.ShockwaveFlash"); 1814 hasFlash = true; 1815 flashVersion = parseFlashVersion(ax.GetVariable("$version")); 1816 } catch (e3) { 1817 isActiveX = false; 1818 } 1819 } 1820 } 1821 } 1822 _flashState.disabled = hasFlash !== true; 1823 _flashState.outdated = flashVersion && _parseFloat(flashVersion) < _parseFloat(_minimumFlashVersion); 1824 _flashState.version = flashVersion || "0.0.0"; 1825 _flashState.pluginType = isPPAPI ? "pepper" : isActiveX ? "activex" : hasFlash ? "netscape" : "unknown"; 1826 }; 1827 /** 1828 * Invoke the Flash detection algorithms immediately upon inclusion so we're not waiting later. 1829 */ 1830 _detectFlashSupport(_ActiveXObject); 1831 /** 1832 * Always assess the `sandboxed` state of the page at important Flash-related moments. 1833 */ 1834 _detectSandbox(true); 1835 /** 1836 * A shell constructor for `ZeroClipboard` client instances. 1837 * 1838 * @constructor 1839 */ 1840 var ZeroClipboard = function() { 1841 if (!(this instanceof ZeroClipboard)) { 1842 return new ZeroClipboard(); 1843 } 1844 if (typeof ZeroClipboard._createClient === "function") { 1845 ZeroClipboard._createClient.apply(this, _args(arguments)); 1846 } 1847 }; 1848 /** 1849 * The ZeroClipboard library's version number. 1850 * 1851 * @static 1852 * @readonly 1853 * @property {string} 1854 */ 1855 _defineProperty(ZeroClipboard, "version", { 1856 value: "2.2.0", 1857 writable: false, 1858 configurable: true, 1859 enumerable: true 1860 }); 1861 /** 1862 * Update or get a copy of the ZeroClipboard global configuration. 1863 * Returns a copy of the current/updated configuration. 1864 * 1865 * @returns Object 1866 * @static 1867 */ 1868 ZeroClipboard.config = function() { 1869 return _config.apply(this, _args(arguments)); 1870 }; 1871 /** 1872 * Diagnostic method that describes the state of the browser, Flash Player, and ZeroClipboard. 1873 * 1874 * @returns Object 1875 * @static 1876 */ 1877 ZeroClipboard.state = function() { 1878 return _state.apply(this, _args(arguments)); 1879 }; 1880 /** 1881 * Check if Flash is unusable for any reason: disabled, outdated, deactivated, etc. 1882 * 1883 * @returns Boolean 1884 * @static 1885 */ 1886 ZeroClipboard.isFlashUnusable = function() { 1887 return _isFlashUnusable.apply(this, _args(arguments)); 1888 }; 1889 /** 1890 * Register an event listener. 1891 * 1892 * @returns `ZeroClipboard` 1893 * @static 1894 */ 1895 ZeroClipboard.on = function() { 1896 return _on.apply(this, _args(arguments)); 1897 }; 1898 /** 1899 * Unregister an event listener. 1900 * If no `listener` function/object is provided, it will unregister all listeners for the provided `eventType`. 1901 * If no `eventType` is provided, it will unregister all listeners for every event type. 1902 * 1903 * @returns `ZeroClipboard` 1904 * @static 1905 */ 1906 ZeroClipboard.off = function() { 1907 return _off.apply(this, _args(arguments)); 1908 }; 1909 /** 1910 * Retrieve event listeners for an `eventType`. 1911 * If no `eventType` is provided, it will retrieve all listeners for every event type. 1912 * 1913 * @returns array of listeners for the `eventType`; if no `eventType`, then a map/hash object of listeners for all event types; or `null` 1914 */ 1915 ZeroClipboard.handlers = function() { 1916 return _listeners.apply(this, _args(arguments)); 1917 }; 1918 /** 1919 * Event emission receiver from the Flash object, forwarding to any registered JavaScript event listeners. 1920 * 1921 * @returns For the "copy" event, returns the Flash-friendly "clipData" object; otherwise `undefined`. 1922 * @static 1923 */ 1924 ZeroClipboard.emit = function() { 1925 return _emit.apply(this, _args(arguments)); 1926 }; 1927 /** 1928 * Create and embed the Flash object. 1929 * 1930 * @returns The Flash object 1931 * @static 1932 */ 1933 ZeroClipboard.create = function() { 1934 return _create.apply(this, _args(arguments)); 1935 }; 1936 /** 1937 * Self-destruct and clean up everything, including the embedded Flash object. 1938 * 1939 * @returns `undefined` 1940 * @static 1941 */ 1942 ZeroClipboard.destroy = function() { 1943 return _destroy.apply(this, _args(arguments)); 1944 }; 1945 /** 1946 * Set the pending data for clipboard injection. 1947 * 1948 * @returns `undefined` 1949 * @static 1950 */ 1951 ZeroClipboard.setData = function() { 1952 return _setData.apply(this, _args(arguments)); 1953 }; 1954 /** 1955 * Clear the pending data for clipboard injection. 1956 * If no `format` is provided, all pending data formats will be cleared. 1957 * 1958 * @returns `undefined` 1959 * @static 1960 */ 1961 ZeroClipboard.clearData = function() { 1962 return _clearData.apply(this, _args(arguments)); 1963 }; 1964 /** 1965 * Get a copy of the pending data for clipboard injection. 1966 * If no `format` is provided, a copy of ALL pending data formats will be returned. 1967 * 1968 * @returns `String` or `Object` 1969 * @static 1970 */ 1971 ZeroClipboard.getData = function() { 1972 return _getData.apply(this, _args(arguments)); 1973 }; 1974 /** 1975 * Sets the current HTML object that the Flash object should overlay. This will put the global 1976 * Flash object on top of the current element; depending on the setup, this may also set the 1977 * pending clipboard text data as well as the Flash object's wrapping element's title attribute 1978 * based on the underlying HTML element and ZeroClipboard configuration. 1979 * 1980 * @returns `undefined` 1981 * @static 1982 */ 1983 ZeroClipboard.focus = ZeroClipboard.activate = function() { 1984 return _focus.apply(this, _args(arguments)); 1985 }; 1986 /** 1987 * Un-overlays the Flash object. This will put the global Flash object off-screen; depending on 1988 * the setup, this may also unset the Flash object's wrapping element's title attribute based on 1989 * the underlying HTML element and ZeroClipboard configuration. 1990 * 1991 * @returns `undefined` 1992 * @static 1993 */ 1994 ZeroClipboard.blur = ZeroClipboard.deactivate = function() { 1995 return _blur.apply(this, _args(arguments)); 1996 }; 1997 /** 1998 * Returns the currently focused/"activated" HTML element that the Flash object is wrapping. 1999 * 2000 * @returns `HTMLElement` or `null` 2001 * @static 2002 */ 2003 ZeroClipboard.activeElement = function() { 2004 return _activeElement.apply(this, _args(arguments)); 820 elements = _prepClip(elements); 821 } 822 for (var i = elements.length; i--; ) { 823 if (elements.hasOwnProperty(i) && elements[i] && elements[i].nodeType === 1) { 824 arrayIndex = 0; 825 while ((arrayIndex = _inArray(elements[i], clippedElements, arrayIndex)) !== -1) { 826 clippedElements.splice(arrayIndex, 1); 827 } 828 var clientIds = _elementMeta[elements[i].zcClippingId]; 829 if (clientIds) { 830 arrayIndex = 0; 831 while ((arrayIndex = _inArray(this.id, clientIds, arrayIndex)) !== -1) { 832 clientIds.splice(arrayIndex, 1); 833 } 834 if (clientIds.length === 0) { 835 if (_globalConfig.autoActivate === true) { 836 _removeEventHandler(elements[i], "mouseover", _elementMouseOver); 837 } 838 delete elements[i].zcClippingId; 839 } 840 } 841 } 842 } 843 } 844 return this; 845 }; 846 ZeroClipboard.prototype.elements = function() { 847 var meta = _clientMeta[this.id]; 848 return meta && meta.elements ? meta.elements.slice(0) : []; 849 }; 850 var _getAllClientsClippedToElement = function(element) { 851 var elementMetaId, clientIds, i, len, client, clients = []; 852 if (element && element.nodeType === 1 && (elementMetaId = element.zcClippingId) && _elementMeta.hasOwnProperty(elementMetaId)) { 853 clientIds = _elementMeta[elementMetaId]; 854 if (clientIds && clientIds.length) { 855 for (i = 0, len = clientIds.length; i < len; i++) { 856 client = _clientMeta[clientIds[i]].instance; 857 if (client && client instanceof ZeroClipboard) { 858 clients.push(client); 859 } 860 } 861 } 862 } 863 return clients; 864 }; 865 _globalConfig.hoverClass = "zeroclipboard-is-hover"; 866 _globalConfig.activeClass = "zeroclipboard-is-active"; 867 _globalConfig.trustedOrigins = null; 868 _globalConfig.allowScriptAccess = null; 869 _globalConfig.useNoCache = true; 870 _globalConfig.moviePath = "ZeroClipboard.swf"; 871 ZeroClipboard.detectFlashSupport = function() { 872 _deprecationWarning("ZeroClipboard.detectFlashSupport", _globalConfig.debug); 873 return _detectFlashSupport(); 874 }; 875 ZeroClipboard.dispatch = function(eventName, args) { 876 if (typeof eventName === "string" && eventName) { 877 var cleanEventName = eventName.toLowerCase().replace(/^on/, ""); 878 if (cleanEventName) { 879 var clients = currentElement && _globalConfig.autoActivate === true ? _getAllClientsClippedToElement(currentElement) : _getAllClients(); 880 for (var i = 0, len = clients.length; i < len; i++) { 881 _receiveEvent.call(clients[i], cleanEventName, args); 882 } 883 } 884 } 885 }; 886 ZeroClipboard.prototype.setHandCursor = function(enabled) { 887 _deprecationWarning("ZeroClipboard.prototype.setHandCursor", _globalConfig.debug); 888 enabled = typeof enabled === "boolean" ? enabled : !!enabled; 889 _setHandCursor(enabled); 890 _globalConfig.forceHandCursor = enabled; 891 return this; 892 }; 893 ZeroClipboard.prototype.reposition = function() { 894 _deprecationWarning("ZeroClipboard.prototype.reposition", _globalConfig.debug); 895 return _reposition(); 896 }; 897 ZeroClipboard.prototype.receiveEvent = function(eventName, args) { 898 _deprecationWarning("ZeroClipboard.prototype.receiveEvent", _globalConfig.debug); 899 if (typeof eventName === "string" && eventName) { 900 var cleanEventName = eventName.toLowerCase().replace(/^on/, ""); 901 if (cleanEventName) { 902 _receiveEvent.call(this, cleanEventName, args); 903 } 904 } 905 }; 906 ZeroClipboard.prototype.setCurrent = function(element) { 907 _deprecationWarning("ZeroClipboard.prototype.setCurrent", _globalConfig.debug); 908 ZeroClipboard.activate(element); 909 return this; 910 }; 911 ZeroClipboard.prototype.resetBridge = function() { 912 _deprecationWarning("ZeroClipboard.prototype.resetBridge", _globalConfig.debug); 913 ZeroClipboard.deactivate(); 914 return this; 915 }; 916 ZeroClipboard.prototype.setTitle = function(newTitle) { 917 _deprecationWarning("ZeroClipboard.prototype.setTitle", _globalConfig.debug); 918 newTitle = newTitle || _globalConfig.title || currentElement && currentElement.getAttribute("title"); 919 if (newTitle) { 920 var htmlBridge = _getHtmlBridge(flashState.bridge); 921 if (htmlBridge) { 922 htmlBridge.setAttribute("title", newTitle); 923 } 924 } 925 return this; 926 }; 927 ZeroClipboard.setDefaults = function(options) { 928 _deprecationWarning("ZeroClipboard.setDefaults", _globalConfig.debug); 929 ZeroClipboard.config(options); 930 }; 931 ZeroClipboard.prototype.addEventListener = function(eventName, func) { 932 _deprecationWarning("ZeroClipboard.prototype.addEventListener", _globalConfig.debug); 933 return this.on(eventName, func); 934 }; 935 ZeroClipboard.prototype.removeEventListener = function(eventName, func) { 936 _deprecationWarning("ZeroClipboard.prototype.removeEventListener", _globalConfig.debug); 937 return this.off(eventName, func); 938 }; 939 ZeroClipboard.prototype.ready = function() { 940 _deprecationWarning("ZeroClipboard.prototype.ready", _globalConfig.debug); 941 return flashState.ready === true; 942 }; 943 var _receiveEvent = function(eventName, args) { 944 eventName = eventName.toLowerCase().replace(/^on/, ""); 945 var cleanVersion = args && args.flashVersion && _parseFlashVersion(args.flashVersion) || null; 946 var element = currentElement; 947 var performCallbackAsync = true; 948 switch (eventName) { 949 case "load": 950 if (cleanVersion) { 951 if (!_isFlashVersionSupported(cleanVersion)) { 952 _receiveEvent.call(this, "onWrongFlash", { 953 flashVersion: cleanVersion 954 }); 955 return; 956 } 957 flashState.outdated = false; 958 flashState.ready = true; 959 flashState.version = cleanVersion; 960 } 961 break; 962 963 case "wrongflash": 964 if (cleanVersion && !_isFlashVersionSupported(cleanVersion)) { 965 flashState.outdated = true; 966 flashState.ready = false; 967 flashState.version = cleanVersion; 968 } 969 break; 970 971 case "mouseover": 972 _addClass(element, _globalConfig.hoverClass); 973 break; 974 975 case "mouseout": 976 if (_globalConfig.autoActivate === true) { 977 ZeroClipboard.deactivate(); 978 } 979 break; 980 981 case "mousedown": 982 _addClass(element, _globalConfig.activeClass); 983 break; 984 985 case "mouseup": 986 _removeClass(element, _globalConfig.activeClass); 987 break; 988 989 case "datarequested": 990 if (element) { 991 var targetId = element.getAttribute("data-clipboard-target"), targetEl = !targetId ? null : document.getElementById(targetId); 992 if (targetEl) { 993 var textContent = targetEl.value || targetEl.textContent || targetEl.innerText; 994 if (textContent) { 995 this.setText(textContent); 996 } 997 } else { 998 var defaultText = element.getAttribute("data-clipboard-text"); 999 if (defaultText) { 1000 this.setText(defaultText); 1001 } 1002 } 1003 } 1004 performCallbackAsync = false; 1005 break; 1006 1007 case "complete": 1008 _deleteOwnProperties(_clipData); 1009 if (element && element !== _safeActiveElement() && element.focus) { 1010 element.focus(); 1011 } 1012 break; 1013 } 1014 var context = element; 1015 var eventArgs = [ this, args ]; 1016 return _dispatchClientCallbacks.call(this, eventName, context, eventArgs, performCallbackAsync); 2005 1017 }; 2006 1018 if (typeof define === "function" && define.amd) { 2007 define(function() { 1019 define([ "require", "exports", "module" ], function(require, exports, module) { 1020 _amdModuleId = module && module.id || null; 2008 1021 return ZeroClipboard; 2009 1022 }); 2010 } else if (typeof module === "object" && module && typeof module.exports === "object" && module.exports) { 1023 } else if (typeof module === "object" && module && typeof module.exports === "object" && module.exports && typeof window.require === "function") { 1024 _cjsModuleId = module.id || null; 2011 1025 module.exports = ZeroClipboard; 2012 1026 } else { … … 2014 1028 } 2015 1029 })(function() { 2016 return this || window;1030 return this; 2017 1031 }());
Note: See TracChangeset
for help on using the changeset viewer.