2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
8 YUI.add('uploader-flash', function (Y, NAME) {
11 * This module provides a UI for file selection and multiple file upload capability using
12 * Flash as a transport engine.
13 * The supported features include: automatic upload queue management, upload progress
14 * tracking, file filtering, server response retrieval and error reporting.
16 * @module uploader-flash
20 // Shorthands for external modules
21 var substitute = Y.Lang.sub,
22 UploaderQueue = Y.Uploader.Queue;
26 * Embed a Flash applications in a standard manner and communicate with it
27 * via External Interface.
32 SWFDetect = Y.SWFDetect,
39 FLASH_CID = "clsid:d27cdb6e-ae6d-11cf-96b8-444553540000",
40 FLASH_TYPE = "application/x-shockwave-flash",
41 FLASH_VER = "10.0.22",
42 EXPRESS_INSTALL_URL = "http://fpdownload.macromedia.com/pub/flashplayer/update/current/swf/autoUpdater.swf?" + Math.random(),
43 EVENT_HANDLER = "SWF.eventHandler",
44 possibleAttributes = {align:"", allowFullScreen:"", allowNetworking:"", allowScriptAccess:"", base:"", bgcolor:"", loop:"", menu:"", name:"", play: "", quality:"", salign:"", scale:"", tabindex:"", wmode:""};
47 * The SWF utility is a tool for embedding Flash applications in HTML pages.
50 * @requires event-custom, node, swfdetect
54 * Creates the SWF instance and keeps the configuration data
57 * @uses Y.Event.Target
59 * @param {String|HTMLElement} id The id of the element, or the element itself that the SWF will be inserted into.
60 * The width and height of the SWF will be set to the width and height of this container element.
61 * @param {String} swfURL The URL of the SWF to be embedded into the page.
62 * @param {Object} p_oAttributes (optional) Configuration parameters for the Flash application and values for Flashvars
63 * to be passed to the SWF. The p_oAttributes object allows the following additional properties:
65 * <dt>version : String</dt>
66 * <dd>The minimum version of Flash required on the user's machine.</dd>
67 * <dt>fixedAttributes : Object</dt>
68 * <dd>An object literal containing one or more of the following String keys and their values: <code>align,
69 * allowFullScreen, allowNetworking, allowScriptAccess, base, bgcolor, menu, name, quality, salign, scale,
70 * tabindex, wmode.</code> event from the thumb</dd>
74 function SWF (p_oElement /*:String*/, swfURL /*:String*/, p_oAttributes /*:Object*/ ) {
76 this._id = Y.guid("yuiswf");
80 var oElement = Node.one(p_oElement);
82 var p_oAttributes = p_oAttributes || {};
84 var flashVersion = p_oAttributes.version || FLASH_VER;
86 var flashVersionSplit = (flashVersion + '').split(".");
87 var isFlashVersionRight = SWFDetect.isFlashVersionAtLeast(parseInt(flashVersionSplit[0], 10), parseInt(flashVersionSplit[1], 10), parseInt(flashVersionSplit[2], 10));
88 var canExpressInstall = (SWFDetect.isFlashVersionAtLeast(8,0,0));
89 var shouldExpressInstall = canExpressInstall && !isFlashVersionRight && p_oAttributes.useExpressInstall;
90 var flashURL = (shouldExpressInstall)?EXPRESS_INSTALL_URL:swfURL;
91 var objstring = '<object ';
93 var flashvarstring = "yId=" + Y.id + "&YUISwfId=" + _id + "&YUIBridgeCallback=" + EVENT_HANDLER + "&allowedDomain=" + document.location.hostname;
95 Y.SWF._instances[_id] = this;
96 if (oElement && (isFlashVersionRight || shouldExpressInstall) && flashURL) {
97 objstring += 'id="' + _id + '" ';
99 objstring += 'classid="' + FLASH_CID + '" ';
101 objstring += 'type="' + FLASH_TYPE + '" data="' + Escape.html(flashURL) + '" ';
107 objstring += 'width="' + w + '" height="' + h + '">';
110 objstring += '<param name="movie" value="' + Escape.html(flashURL) + '"/>';
113 for (var attribute in p_oAttributes.fixedAttributes) {
114 if (possibleAttributes.hasOwnProperty(attribute)) {
115 objstring += '<param name="' + Escape.html(attribute) + '" value="' + Escape.html(p_oAttributes.fixedAttributes[attribute]) + '"/>';
119 for (var flashvar in p_oAttributes.flashVars) {
120 var fvar = p_oAttributes.flashVars[flashvar];
121 if (Lang.isString(fvar)) {
122 flashvarstring += "&" + Escape.html(flashvar) + "=" + Escape.html(encodeURIComponent(fvar));
126 if (flashvarstring) {
127 objstring += '<param name="flashVars" value="' + flashvarstring + '"/>';
130 objstring += "</object>";
131 //using innerHTML as setHTML/setContent causes some issues with ExternalInterface for IE versions of the player
132 oElement.set("innerHTML", objstring);
134 this._swf = Node.one("#" + _id);
137 * Fired when the Flash player version on the user's machine is
138 * below the required value.
140 * @event wrongflashversion
143 event.type = "wrongflashversion";
144 this.publish("wrongflashversion", {fireOnce:true});
145 this.fire("wrongflashversion", event);
151 * The static collection of all instances of the SWFs on the page.
152 * @property _instances
156 SWF._instances = SWF._instances || {};
160 * Handles an event coming from within the SWF and delegate it
161 * to a specific instance of SWF.
162 * @method eventHandler
163 * @param swfid {String} the id of the SWF dispatching the event
164 * @param event {Object} the event being transmitted.
166 SWF.eventHandler = function (swfid, event) {
167 SWF._instances[swfid]._eventHandler(event);
173 * Propagates a specific event from Flash to JS.
174 * @method _eventHandler
175 * @param event {Object} The event to be propagated from Flash.
177 _eventHandler: function(event) {
178 if (event.type === "swfReady") {
179 this.publish("swfReady", {fireOnce:true});
180 this.fire("swfReady", event);
181 } else if(event.type === "log") {
183 this.fire(event.type, event);
188 * Calls a specific function exposed by the SWF's
191 * @param func {String} the name of the function to call
192 * @param args {Array} the set of arguments to pass to the function.
195 callSWF: function (func, args)
200 if (this._swf._node[func]) {
201 return(this._swf._node[func].apply(this._swf._node, args));
208 * Public accessor to the unique name of the SWF instance.
211 * @return {String} Unique name of the SWF instance.
215 return "SWF " + this._id;
219 Y.augment(SWF, Y.EventTarget);
223 * The FileFlash class provides a wrapper for a file pointer stored in Flash. The File wrapper
224 * also implements the mechanics for uploading a file and tracking its progress.
228 * The class provides a wrapper for a file pointer in Flash.
232 * @param {Object} config Configuration object.
235 var FileFlash = function(o) {
236 FileFlash.superclass.constructor.apply(this, arguments);
239 Y.extend(FileFlash, Y.Base, {
242 * Construction logic executed during FileFlash instantiation.
244 * @method initializer
247 initializer : function (cfg) {
248 if (!this.get("id")) {
249 this._set("id", Y.guid("file"));
254 * Handler of events dispatched by the Flash player.
256 * @method _swfEventHandler
257 * @param {Event} event The event object received from the Flash player.
260 _swfEventHandler: function (event) {
261 if (event.id === this.get("id")) {
262 switch (event.type) {
264 * Signals that this file's upload has started.
267 * @param event {Event} The event object for the `uploadstart` with the
271 * <dd>The Y.SWF instance of Flash uploader that's handling the upload.</dd>
275 this.fire("uploadstart", {uploader: this.get("uploader")});
277 case "uploadprogress":
280 * Signals that progress has been made on the upload of this file.
282 * @event uploadprogress
283 * @param event {Event} The event object for the `uploadprogress` with the
286 * <dt>originEvent</dt>
287 * <dd>The original event fired by the Flash uploader instance.</dd>
288 * <dt>bytesLoaded</dt>
289 * <dd>The number of bytes of the file that has been uploaded.</dd>
290 * <dt>bytesTotal</dt>
291 * <dd>The total number of bytes in the file (the file size)</dd>
292 * <dt>percentLoaded</dt>
293 * <dd>The fraction of the file that has been uploaded, out of 100.</dd>
296 this.fire("uploadprogress", {originEvent: event,
297 bytesLoaded: event.bytesLoaded,
298 bytesTotal: event.bytesTotal,
299 percentLoaded: Math.min(100, Math.round(10000*event.bytesLoaded/event.bytesTotal)/100)
301 this._set("bytesUploaded", event.bytesLoaded);
303 case "uploadcomplete":
306 * Signals that this file's upload has completed, but data has not yet been received from the server.
308 * @event uploadfinished
309 * @param event {Event} The event object for the `uploadfinished` with the
312 * <dt>originEvent</dt>
313 * <dd>The original event fired by the Flash player instance.</dd>
316 this.fire("uploadfinished", {originEvent: event});
318 case "uploadcompletedata":
320 * Signals that this file's upload has completed and data has been received from the server.
322 * @event uploadcomplete
323 * @param event {Event} The event object for the `uploadcomplete` with the
326 * <dt>originEvent</dt>
327 * <dd>The original event fired by the Flash player instance.</dd>
329 * <dd>The data returned by the server.</dd>
332 this.fire("uploadcomplete", {originEvent: event,
338 * Signals that this file's upload has been cancelled.
340 * @event uploadcancel
341 * @param event {Event} The event object for the `uploadcancel` with the
344 * <dt>originEvent</dt>
345 * <dd>The original event fired by the Flash player instance.</dd>
348 this.fire("uploadcancel", {originEvent: event});
353 * Signals that this file's upload has encountered an error.
356 * @param event {Event} The event object for the `uploaderror` with the
359 * <dt>originEvent</dt>
360 * <dd>The original event fired by the Flash player instance.</dd>
362 * <dd>The status code reported by the Flash Player. If it's an HTTP error,
363 * then this corresponds to the HTTP status code received by the uploader.</dd>
364 * <dt>statusText</dt>
365 * <dd>The text of the error event reported by the Flash Player.</dd>
367 * <dd>Either "http" (if it's an HTTP error), or "io" (if it's a network transmission
371 this.fire("uploaderror", {originEvent: event, status: event.status, statusText: event.message, source: event.source});
378 * Starts the upload of a specific file.
380 * @method startUpload
381 * @param url {String} The URL to upload the file to.
382 * @param parameters {Object} (optional) A set of key-value pairs to send as variables along with the file upload HTTP request.
383 * @param fileFieldName {String} (optional) The name of the POST variable that should contain the uploaded file ('Filedata' by default)
385 startUpload: function(url, parameters, fileFieldName) {
387 if (this.get("uploader")) {
389 var myUploader = this.get("uploader"),
390 fileField = fileFieldName || "Filedata",
392 params = parameters || null;
394 this._set("bytesUploaded", 0);
396 myUploader.on("uploadstart", this._swfEventHandler, this);
397 myUploader.on("uploadprogress", this._swfEventHandler, this);
398 myUploader.on("uploadcomplete", this._swfEventHandler, this);
399 myUploader.on("uploadcompletedata", this._swfEventHandler, this);
400 myUploader.on("uploaderror", this._swfEventHandler, this);
402 myUploader.callSWF("upload", [id, url, params, fileField]);
408 * Cancels the upload of a specific file, if currently in progress.
410 * @method cancelUpload
412 cancelUpload: function () {
413 if (this.get("uploader")) {
414 this.get("uploader").callSWF("cancel", [this.get("id")]);
415 this.fire("uploadcancel");
422 * The identity of the class.
434 * The type of transport.
446 * Static property used to define the default attribute configuration of
457 * A String containing the unique id of the file wrapped by the FileFlash instance.
458 * The id is supplied by the Flash player uploader.
465 writeOnce: "initOnly",
470 * The size of the file wrapped by FileFlash. This value is supplied by the Flash player uploader.
477 writeOnce: "initOnly",
482 * The name of the file wrapped by FileFlash. This value is supplied by the Flash player uploader.
489 writeOnce: "initOnly",
494 * The date that the file wrapped by FileFlash was created on. This value is supplied by the Flash player uploader.
496 * @attribute dateCreated
501 writeOnce: "initOnly",
506 * The date that the file wrapped by FileFlash was last modified on. This value is supplied by the Flash player uploader.
508 * @attribute dateModified
513 writeOnce: "initOnly",
518 * The number of bytes of the file that has been uploaded to the server. This value is
519 * non-zero only while a file is being uploaded.
521 * @attribute bytesUploaded
531 * The type of the file wrapped by FileFlash. This value is provided by the Flash player
539 writeOnce: "initOnly",
544 * The instance of Y.SWF wrapping the Flash player uploader associated with this file.
551 writeOnce: "initOnly",
557 Y.FileFlash = FileFlash;
559 * This module provides a UI for file selection and multiple file upload capability
560 * using Flash as a transport engine.
561 * @class UploaderFlash
563 * @param {Object} config Configuration object.
568 function UploaderFlash() {
569 UploaderFlash.superclass.constructor.apply ( this, arguments );
574 Y.UploaderFlash = Y.extend(UploaderFlash, Y.Widget, {
577 * Stored value of the current button state (based on
578 * mouse events dispatched by the Flash player)
579 * @property _buttonState
586 * Stored value of the current button focus state (based
587 * on keyboard and mouse events).
588 * @property _buttonFocus
595 * Stored value of the unique id for the container that holds the
598 * @property _swfContainerId
602 _swfContainerId: null,
605 * Stored reference to the instance of SWF used to host the
608 * @property _swfReference
615 * Stored reference to the instance of Uploader.Queue used to manage
616 * the upload process. This is a read-only property that only exists
617 * during an active upload process. Only one queue can be active at
618 * a time; if an upload start is attempted while a queue is active,
619 * it will be ignored.
622 * @type {Y.Uploader.Queue}
627 * Stored event bindings for keyboard navigation to and from the uploader.
629 * @property _tabElementBindings
633 _tabElementBindings: null,
637 * Construction logic executed during UploaderFlash instantiation.
639 * @method initializer
642 initializer : function () {
644 // Assign protected variable values
645 this._swfContainerId = Y.guid("uploader");
646 this._swfReference = null;
648 this._buttonState = "up";
649 this._buttonFocus = null;
650 this._tabElementBindings = null;
653 // Publish available events
656 * Signals that files have been selected.
659 * @param event {Event} The event object for the `fileselect` with the
663 * <dd>An `Array` of files selected by the user, encapsulated
664 * in Y.FileFlash objects.</dd>
667 this.publish("fileselect");
670 * Signals that an upload of multiple files has been started.
673 * @param event {Event} The event object for the `uploadstart`.
675 this.publish("uploadstart");
678 * Signals that an upload of a specific file has started.
680 * @event fileuploadstart
681 * @param event {Event} The event object for the `fileuploadstart` with the
685 * <dd>A reference to the Y.File that dispatched the event.</dd>
686 * <dt>originEvent</dt>
687 * <dd>The original event dispatched by Y.File.</dd>
690 this.publish("fileuploadstart");
693 * Reports on upload progress of a specific file.
695 * @event uploadprogress
696 * @param event {Event} The event object for the `uploadprogress` with the
699 * <dt>bytesLoaded</dt>
700 * <dd>The number of bytes of the file that has been uploaded</dd>
701 * <dt>bytesTotal</dt>
702 * <dd>The total number of bytes in the file</dd>
703 * <dt>percentLoaded</dt>
704 * <dd>The fraction of the file that has been uploaded, out of 100</dd>
705 * <dt>originEvent</dt>
706 * <dd>The original event dispatched by the SWF uploader</dd>
709 this.publish("uploadprogress");
712 * Reports on the total upload progress of the file list.
714 * @event totaluploadprogress
715 * @param event {Event} The event object for the `totaluploadprogress` with the
718 * <dt>bytesLoaded</dt>
719 * <dd>The number of bytes of the file list that has been uploaded</dd>
720 * <dt>bytesTotal</dt>
721 * <dd>The total number of bytes in the file list</dd>
722 * <dt>percentLoaded</dt>
723 * <dd>The fraction of the file list that has been uploaded, out of 100</dd>
726 this.publish("totaluploadprogress");
729 * Signals that a single file upload has been completed.
731 * @event uploadcomplete
732 * @param event {Event} The event object for the `uploadcomplete` with the
736 * <dd>The pointer to the instance of `Y.File` whose upload has been completed.</dd>
737 * <dt>originEvent</dt>
738 * <dd>The original event fired by the SWF Uploader</dd>
740 * <dd>Data returned by the server.</dd>
743 this.publish("uploadcomplete");
746 * Signals that the upload process of the entire file list has been completed.
748 * @event alluploadscomplete
749 * @param event {Event} The event object for the `alluploadscomplete`.
751 this.publish("alluploadscomplete");
754 * Signals that a error has occurred in a specific file's upload process.
757 * @param event {Event} The event object for the `uploaderror` with the
760 * <dt>originEvent</dt>
761 * <dd>The original error event fired by the SWF Uploader. </dd>
763 * <dd>The pointer at the instance of Y.FileFlash that returned the error.</dd>
765 * <dd>The source of the upload error, either "io" or "http"</dd>
767 * <dd>The message that accompanied the error. Corresponds to the text of
768 * the error in cases where source is "io", and to the HTTP status for
769 cases where source is "http".</dd>
772 this.publish("uploaderror");
775 * Signals that a mouse has begun hovering over the `Select Files` button.
778 * @param event {Event} The event object for the `mouseenter` event.
780 this.publish("mouseenter");
783 * Signals that a mouse has stopped hovering over the `Select Files` button.
786 * @param event {Event} The event object for the `mouseleave` event.
788 this.publish("mouseleave");
791 * Signals that a mouse button has been pressed over the `Select Files` button.
794 * @param event {Event} The event object for the `mousedown` event.
796 this.publish("mousedown");
799 * Signals that a mouse button has been released over the `Select Files` button.
802 * @param event {Event} The event object for the `mouseup` event.
804 this.publish("mouseup");
807 * Signals that a mouse has been clicked over the `Select Files` button.
810 * @param event {Event} The event object for the `click` event.
812 this.publish("click");
816 * Creates the DOM structure for the UploaderFlash.
817 * UploaderFlash's DOM structure consists of two layers: the base "Select Files"
818 * button that can be replaced by the developer's widget of choice; and a transparent
819 * Flash overlay positoned above the button that captures all input events.
820 * The `position` style attribute of the `boundingBox` of the `Uploader` widget
821 * is forced to be `relative`, in order to accommodate the Flash player overlay
822 * (which is `position`ed `absolute`ly).
827 renderUI : function () {
828 var boundingBox = this.get("boundingBox"),
829 contentBox = this.get('contentBox'),
830 selFilesButton = this.get("selectFilesButton"),
831 flashContainer = Y.Node.create(substitute(UploaderFlash.FLASH_CONTAINER, {
832 swfContainerId: this._swfContainerId
837 wmode: "transparent",
838 allowScriptAccess:"always",
839 allowNetworking:"all",
844 boundingBox.setStyle("position", "relative");
845 selFilesButton.setStyles({width: "100%", height: "100%"});
846 contentBox.append(selFilesButton);
847 contentBox.append(flashContainer);
849 this._swfReference = new Y.SWF(flashContainer, this.get("swfURL"), params);
853 * Binds handlers to the UploaderFlash UI events and propagates attribute
854 * values to the Flash player.
855 * The propagation of initial values is set to occur once the Flash player
856 * instance is ready (as indicated by the `swfReady` event.)
861 bindUI : function () {
863 this._swfReference.on("swfReady", function () {
864 this._setMultipleFiles();
865 this._setFileFilters();
866 this._triggerEnabled();
867 this._attachTabElements();
868 this.after("multipleFilesChange", this._setMultipleFiles, this);
869 this.after("fileFiltersChange", this._setFileFilters, this);
870 this.after("enabledChange", this._triggerEnabled, this);
871 this.after("tabElementsChange", this._attachTabElements);
874 this._swfReference.on("fileselect", this._updateFileList, this);
878 // this._swfReference.on("trace", function (ev) {console.log(ev.message);});
880 this._swfReference.on("mouseenter", function () {
881 this.fire("mouseenter");
882 this._setButtonClass("hover", true);
883 if (this._buttonState === "down") {
884 this._setButtonClass("active", true);
888 this._swfReference.on("mouseleave", function () {
889 this.fire("mouseleave");
890 this._setButtonClass("hover", false);
891 this._setButtonClass("active", false);
894 this._swfReference.on("mousedown", function () {
895 this.fire("mousedown");
896 this._buttonState = "down";
897 this._setButtonClass("active", true);
900 this._swfReference.on("mouseup", function () {
901 this.fire("mouseup");
902 this._buttonState = "up";
903 this._setButtonClass("active", false);
906 this._swfReference.on("click", function () {
908 this._buttonFocus = true;
909 this._setButtonClass("focus", true);
910 Y.one("body").focus();
911 this._swfReference._swf.focus();
916 * Attaches keyboard bindings to enabling tabbing to and from the instance of the Flash
917 * player in the Uploader widget. If the previous and next elements are specified, the
918 * keyboard bindings enable the user to tab from the `tabElements["from"]` node to the
919 * Flash-powered "Select Files" button, and to the `tabElements["to"]` node.
921 * @method _attachTabElements
923 * @param ev {Event} Optional event payload if called as a `tabElementsChange` handler.
925 _attachTabElements : function () {
926 if (this.get("tabElements") !== null && this.get("tabElements").from !== null && this.get("tabElements").to !== null) {
928 if (this._tabElementBindings !== null) {
929 this._tabElementBindings.from.detach();
930 this._tabElementBindings.to.detach();
931 this._tabElementBindings.tabback.detach();
932 this._tabElementBindings.tabforward.detach();
933 this._tabElementBindings.focus.detach();
934 this._tabElementBindings.blur.detach();
937 this._tabElementBindings = {};
940 var fromElement = Y.one(this.get("tabElements").from),
941 toElement = Y.one(this.get("tabElements").to);
944 this._tabElementBindings.from = fromElement.on("keydown", function (ev) {
945 if (ev.keyCode === 9 && !ev.shiftKey) {
947 this._swfReference._swf.setAttribute("tabindex", 0);
948 this._swfReference._swf.setAttribute("role", "button");
949 this._swfReference._swf.setAttribute("aria-label", this.get("selectButtonLabel"));
950 this._swfReference._swf.focus();
954 this._tabElementBindings.to = toElement.on("keydown", function (ev) {
955 if (ev.keyCode === 9 && ev.shiftKey) {
957 this._swfReference._swf.setAttribute("tabindex", 0);
958 this._swfReference._swf.setAttribute("role", "button");
959 this._swfReference._swf.setAttribute("aria-label", this.get("selectButtonLabel"));
960 this._swfReference._swf.focus();
964 this._tabElementBindings.tabback = this._swfReference.on("tabback", function () {
965 this._swfReference._swf.blur();
966 setTimeout(function () {
971 this._tabElementBindings.tabforward = this._swfReference.on("tabforward", function () {
972 this._swfReference._swf.blur();
973 setTimeout(function () {
978 this._tabElementBindings.focus = this._swfReference._swf.on("focus", function () {
979 this._buttonFocus = true;
980 this._setButtonClass("focus", true);
983 this._tabElementBindings.blur = this._swfReference._swf.on("blur", function () {
984 this._buttonFocus = false;
985 this._setButtonClass("focus", false);
988 else if (this._tabElementBindings !== null) {
989 this._tabElementBindings.from.detach();
990 this._tabElementBindings.to.detach();
991 this._tabElementBindings.tabback.detach();
992 this._tabElementBindings.tabforward.detach();
993 this._tabElementBindings.focus.detach();
994 this._tabElementBindings.blur.detach();
1000 * Adds or removes a specified state CSS class to the underlying uploader button.
1002 * @method _setButtonClass
1004 * @param state {String} The name of the state enumerated in `buttonClassNames` attribute
1005 * from which to derive the needed class name.
1006 * @param add {Boolean} A Boolean indicating whether to add or remove the class.
1008 _setButtonClass : function (state, add) {
1010 this.get("selectFilesButton").addClass(this.get("buttonClassNames")[state]);
1013 this.get("selectFilesButton").removeClass(this.get("buttonClassNames")[state]);
1019 * Syncs the state of the `fileFilters` attribute between the instance of UploaderFlash
1020 * and the Flash player.
1022 * @method _setFileFilters
1025 _setFileFilters : function () {
1026 if (this._swfReference && this.get("fileFilters").length > 0) {
1027 this._swfReference.callSWF("setFileFilters", [this.get("fileFilters")]);
1034 * Syncs the state of the `multipleFiles` attribute between this class
1035 * and the Flash uploader.
1037 * @method _setMultipleFiles
1040 _setMultipleFiles : function () {
1041 if (this._swfReference) {
1042 this._swfReference.callSWF("setAllowMultipleFiles", [this.get("multipleFiles")]);
1047 * Syncs the state of the `enabled` attribute between this class
1048 * and the Flash uploader.
1050 * @method _triggerEnabled
1053 _triggerEnabled : function () {
1054 if (this.get("enabled")) {
1055 this._swfReference.callSWF("enable");
1056 this._swfReference._swf.setAttribute("aria-disabled", "false");
1057 this._setButtonClass("disabled", false);
1060 this._swfReference.callSWF("disable");
1061 this._swfReference._swf.setAttribute("aria-disabled", "true");
1062 this._setButtonClass("disabled", true);
1067 * Getter for the `fileList` attribute
1069 * @method _getFileList
1072 _getFileList : function () {
1073 return this._fileList.concat();
1077 * Setter for the `fileList` attribute
1079 * @method _setFileList
1082 _setFileList : function (val) {
1083 this._fileList = val.concat();
1084 return this._fileList.concat();
1088 * Adjusts the content of the `fileList` based on the results of file selection
1089 * and the `appendNewFiles` attribute. If the `appendNewFiles` attribute is true,
1090 * then selected files are appended to the existing list; otherwise, the list is
1091 * cleared and populated with the newly selected files.
1093 * @method _updateFileList
1094 * @param ev {Event} The file selection event received from the uploader.
1097 _updateFileList : function (ev) {
1099 Y.one("body").focus();
1100 this._swfReference._swf.focus();
1103 var newfiles = ev.fileList,
1104 fileConfObjects = [],
1106 swfRef = this._swfReference,
1107 filterFunc = this.get("fileFilterFunction"),
1110 Y.each(newfiles, function (value) {
1111 var newFileConf = {};
1112 newFileConf.id = value.fileId;
1113 newFileConf.name = value.fileReference.name;
1114 newFileConf.size = value.fileReference.size;
1115 newFileConf.type = value.fileReference.type;
1116 newFileConf.dateCreated = value.fileReference.creationDate;
1117 newFileConf.dateModified = value.fileReference.modificationDate;
1118 newFileConf.uploader = swfRef;
1120 fileConfObjects.push(newFileConf);
1124 Y.each(fileConfObjects, function (value) {
1125 var newfile = new Y.FileFlash(value);
1126 if (filterFunc(newfile)) {
1127 parsedFiles.push(newfile);
1132 Y.each(fileConfObjects, function (value) {
1133 parsedFiles.push(new Y.FileFlash(value));
1137 if (parsedFiles.length > 0) {
1138 oldfiles = this.get("fileList");
1140 this.set("fileList",
1141 this.get("appendNewFiles") ? oldfiles.concat(parsedFiles) : parsedFiles );
1143 this.fire("fileselect", { fileList: parsedFiles });
1151 * Handles and retransmits events fired by `Y.FileFlash` and `Y.Uploader.Queue`.
1153 * @method _uploadEventHandler
1154 * @param event The event dispatched during the upload process.
1157 _uploadEventHandler : function (event) {
1159 switch (event.type) {
1160 case "file:uploadstart":
1161 this.fire("fileuploadstart", event);
1163 case "file:uploadprogress":
1164 this.fire("uploadprogress", event);
1166 case "uploaderqueue:totaluploadprogress":
1167 this.fire("totaluploadprogress", event);
1169 case "file:uploadcomplete":
1170 this.fire("uploadcomplete", event);
1172 case "uploaderqueue:alluploadscomplete":
1174 this.fire("alluploadscomplete", event);
1176 case "file:uploaderror": //overflow intentional
1177 case "uploaderqueue:uploaderror":
1178 this.fire("uploaderror", event);
1180 case "file:uploadcancel": // overflow intentional
1181 case "uploaderqueue:uploadcancel":
1182 this.fire("uploadcancel", event);
1191 * Starts the upload of a specific file.
1194 * @param file {Y.FileFlash} Reference to the instance of the file to be uploaded.
1195 * @param url {String} The URL to upload the file to.
1196 * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request.
1197 * If not specified, the values from the attribute `postVarsPerFile` are used instead.
1199 upload : function (file, url, postvars) {
1201 var uploadURL = url || this.get("uploadURL"),
1202 postVars = postvars || this.get("postVarsPerFile"),
1203 fileId = file.get("id");
1205 postVars = postVars.hasOwnProperty(fileId) ? postVars[fileId] : postVars;
1207 if (file instanceof Y.FileFlash) {
1209 file.on("uploadstart", this._uploadEventHandler, this);
1210 file.on("uploadprogress", this._uploadEventHandler, this);
1211 file.on("uploadcomplete", this._uploadEventHandler, this);
1212 file.on("uploaderror", this._uploadEventHandler, this);
1213 file.on("uploadcancel", this._uploadEventHandler, this);
1215 file.startUpload(uploadURL, postVars, this.get("fileFieldName"));
1220 * Starts the upload of all files on the file list, using an automated queue.
1223 * @param url {String} The URL to upload the files to.
1224 * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request.
1225 * If not specified, the values from the attribute `postVarsPerFile` are used instead.
1227 uploadAll : function (url, postvars) {
1228 this.uploadThese(this.get("fileList"), url, postvars);
1232 * Starts the upload of the files specified in the first argument, using an automated queue.
1234 * @method uploadThese
1235 * @param files {Array} The list of files to upload.
1236 * @param url {String} The URL to upload the files to.
1237 * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request.
1238 * If not specified, the values from the attribute `postVarsPerFile` are used instead.
1240 uploadThese : function (files, url, postvars) {
1242 var uploadURL = url || this.get("uploadURL"),
1243 postVars = postvars || this.get("postVarsPerFile");
1245 this.queue = new UploaderQueue({
1246 simUploads: this.get("simLimit"),
1247 errorAction: this.get("errorAction"),
1248 fileFieldName: this.get("fileFieldName"),
1250 uploadURL: uploadURL,
1251 perFileParameters: postVars,
1252 retryCount: this.get("retryCount")
1255 this.queue.on("uploadstart", this._uploadEventHandler, this);
1256 this.queue.on("uploadprogress", this._uploadEventHandler, this);
1257 this.queue.on("totaluploadprogress", this._uploadEventHandler, this);
1258 this.queue.on("uploadcomplete", this._uploadEventHandler, this);
1259 this.queue.on("alluploadscomplete", this._uploadEventHandler, this);
1260 this.queue.on("alluploadscancelled", function () {this.queue = null;}, this);
1261 this.queue.on("uploaderror", this._uploadEventHandler, this);
1262 this.queue.startUpload();
1264 this.fire("uploadstart");
1271 * The template for the Flash player container. Since the Flash player container needs
1272 * to completely overlay the &lquot;Select Files&rqot; control, it's positioned absolutely,
1273 * with width and height set to 100% of the parent.
1275 * @property FLASH_CONTAINER
1278 * @default '<div id="{swfContainerId}" style="position:absolute; top:0px; left: 0px; margin: 0; padding: 0;
1279 * border: 0; width:100%; height:100%"></div>'
1281 FLASH_CONTAINER: '<div id="{swfContainerId}" style="position:absolute; top:0px; left: 0px; margin: 0; ' +
1282 'padding: 0; border: 0; width:100%; height:100%"></div>',
1285 * The template for the "Select Files" button.
1287 * @property SELECT_FILES_BUTTON
1290 * @default "<button type='button' class='yui3-button' tabindex='-1'>{selectButtonLabel}</button>"
1292 SELECT_FILES_BUTTON: "<button type='button' class='yui3-button' tabindex='-1'>{selectButtonLabel}</button>",
1295 * The static property reflecting the type of uploader that `Y.Uploader`
1296 * aliases. The UploaderFlash value is `"flash"`.
1305 * The identity of the widget.
1309 * @default 'uploader'
1317 * Static property used to define the default attribute configuration of
1328 * A Boolean indicating whether newly selected files should be appended
1329 * to the existing file list, or whether they should replace it.
1331 * @attribute appendNewFiles
1340 * The names of CSS classes that correspond to different button states
1341 * of the "Select Files" control. These classes are assigned to the
1342 * "Select Files" control based on the mouse states reported by the
1343 * Flash player. The keys for the class names are:
1345 * <li> <strong>`hover`</strong>: the class corresponding to mouse hovering over
1346 * the "Select Files" button.</li>
1347 * <li> <strong>`active`</strong>: the class corresponding to mouse down state of
1348 * the "Select Files" button.</li>
1349 * <li> <strong>`disabled`</strong>: the class corresponding to the disabled state
1350 * of the "Select Files" button.</li>
1351 * <li> <strong>`focus`</strong>: the class corresponding to the focused state of
1352 * the "Select Files" button.</li>
1354 * @attribute buttonClassNames
1356 * @default { hover: "yui3-button-hover",
1357 * active: "yui3-button-active",
1358 * disabled: "yui3-button-disabled",
1359 * focus: "yui3-button-selected"
1364 "hover": "yui3-button-hover",
1365 "active": "yui3-button-active",
1366 "disabled": "yui3-button-disabled",
1367 "focus": "yui3-button-selected"
1372 * A Boolean indicating whether the uploader is enabled or disabled for user input.
1374 * @attribute enabled
1383 * The action performed when an upload error occurs for a specific file being uploaded.
1384 * The possible values are:
1386 * <li> <strong>`UploaderQueue.CONTINUE`</strong>: the error is ignored and the upload process is continued.</li>
1387 * <li> <strong>`UploaderQueue.STOP`</strong>: the upload process is stopped as soon as any other parallel file
1388 * uploads are finished.</li>
1389 * <li> <strong>`UploaderQueue.RESTART_ASAP`</strong>: the file is added back to the front of the queue.</li>
1390 * <li> <strong>`UploaderQueue.RESTART_AFTER`</strong>: the file is added to the back of the queue.</li>
1392 * @attribute errorAction
1394 * @default UploaderQueue.CONTINUE
1398 validator: function (val) {
1400 val === UploaderQueue.CONTINUE ||
1401 val === UploaderQueue.STOP ||
1402 val === UploaderQueue.RESTART_ASAP ||
1403 val === UploaderQueue.RESTART_AFTER
1409 * An array indicating what fileFilters should be applied to the file
1410 * selection dialog. Each element in the array should be an object with
1411 * the following key-value pairs:
1413 * description : String
1414 extensions: String of the form &lquot;*.ext1;*.ext2;*.ext3;...&rquot;
1416 * @attribute fileFilters
1425 * A filtering function that is applied to every file selected by the user.
1426 * The function receives the `Y.File` object and must return a Boolean value.
1427 * If a `false` value is returned, the file in question is not added to the
1428 * list of files to be uploaded.
1429 * Use this function to put limits on file sizes or check the file names for
1430 * correct extension, but make sure that a server-side check is also performed,
1431 * since any client-side restrictions are only advisory and can be circumvented.
1433 * @attribute fileFilterFunction
1437 fileFilterFunction: {
1442 * A String specifying what should be the POST field name for the file
1443 * content in the upload request.
1445 * @attribute fileFieldName
1454 * The array of files to be uploaded. All elements in the array
1455 * must be instances of `Y.FileFlash` and be instantiated with a `fileId`
1456 * retrieved from an instance of the uploader.
1458 * @attribute fileList
1464 getter: "_getFileList",
1465 setter: "_setFileList"
1469 * A Boolean indicating whether multiple file selection is enabled.
1471 * @attribute multipleFiles
1480 * An object, keyed by `fileId`, containing sets of key-value pairs
1481 * that should be passed as POST variables along with each corresponding
1482 * file. This attribute is only used if no POST variables are specifed
1483 * in the upload method call.
1485 * @attribute postVarsPerFile
1494 * The label for the "Select Files" widget. This is the value that replaces the
1495 * `{selectButtonLabel}` token in the `SELECT_FILES_BUTTON` template.
1497 * @attribute selectButtonLabel
1499 * @default "Select Files"
1501 selectButtonLabel: {
1502 value: "Select Files"
1506 * The widget that serves as the "Select Files" control for the file uploader
1509 * @attribute selectFilesButton
1510 * @type {Node | Widget}
1511 * @default A standard HTML button with YUI CSS Button skin.
1513 selectFilesButton : {
1514 valueFn: function () {
1515 return Y.Node.create(substitute(Y.UploaderFlash.SELECT_FILES_BUTTON, {selectButtonLabel: this.get("selectButtonLabel")}));
1520 * The number of files that can be uploaded
1521 * simultaneously if the automatic queue management
1522 * is used. This value can be in the range between 2
1525 * @attribute simLimit
1531 validator: function (val) {
1532 return (val >= 2 && val <= 5);
1537 * The URL to the SWF file of the flash uploader. A copy local to
1538 * the server that hosts the page on which the uploader appears is
1543 * @default "flashuploader.swf" with a
1544 * random GET parameter for IE (to prevent buggy behavior when the SWF
1548 valueFn: function () {
1549 var prefix = "flashuploader.swf";
1552 return (prefix + "?t=" + Y.guid("uploader"));
1560 * The id's or `Node` references of the DOM elements that precede
1561 * and follow the `Select Files` button in the tab order. Specifying
1562 * these allows keyboard navigation to and from the Flash player
1563 * layer of the uploader.
1564 * The two keys corresponding to the DOM elements are:
1566 * <li> `from`: the id or the `Node` reference corresponding to the
1567 * DOM element that precedes the `Select Files` button in the tab order.</li>
1568 * <li> `to`: the id or the `Node` reference corresponding to the
1569 * DOM element that follows the `Select Files` button in the tab order.</li>
1571 * @attribute tabElements
1580 * The URL to which file upload requested are POSTed. Only used if a different url is not passed to the upload method call.
1582 * @attribute uploadURL
1591 * The number of times to try re-uploading a file that failed to upload before
1592 * cancelling its upload.
1594 * @attribute retryCount
1604 Y.UploaderFlash.Queue = UploaderQueue;