src/cm/media/js/lib/yui/yui_3.10.3/build/uploader-html5/uploader-html5-debug.js
changeset 525 89ef5ed3c48b
equal deleted inserted replaced
524:322d0feea350 525:89ef5ed3c48b
       
     1 /*
       
     2 YUI 3.10.3 (build 2fb5187)
       
     3 Copyright 2013 Yahoo! Inc. All rights reserved.
       
     4 Licensed under the BSD License.
       
     5 http://yuilibrary.com/license/
       
     6 */
       
     7 
       
     8 YUI.add('uploader-html5', function (Y, NAME) {
       
     9 
       
    10 /**
       
    11 * This module provides a UI for file selection and multiple file upload capability using
       
    12 * HTML5 XMLHTTPRequest Level 2 as a transport engine.
       
    13 * The supported features include: automatic upload queue management, upload progress
       
    14 * tracking, drag-and-drop support, server response retrieval and error reporting.
       
    15 *
       
    16 * @module uploader-html5
       
    17 */
       
    18 
       
    19 // Shorthands for the external modules
       
    20 var  substitute  = Y.Lang.sub,
       
    21      UploaderQueue = Y.Uploader.Queue;
       
    22 
       
    23 /**
       
    24 * This module provides a UI for file selection and multiple file upload capability using
       
    25 * HTML5 XMLHTTPRequest Level 2 as a transport engine.
       
    26 * @class UploaderHTML5
       
    27 * @extends Widget
       
    28 * @constructor
       
    29 */
       
    30 function UploaderHTML5() {
       
    31     UploaderHTML5.superclass.constructor.apply ( this, arguments );
       
    32 }
       
    33 
       
    34 
       
    35 
       
    36 Y.UploaderHTML5 = Y.extend( UploaderHTML5, Y.Widget, {
       
    37 
       
    38     /**
       
    39     * Stored reference to the instance of the file input field used to
       
    40     * initiate the file selection dialog.
       
    41     *
       
    42     * @property _fileInputField
       
    43     * @type {Node}
       
    44     * @protected
       
    45     */
       
    46     _fileInputField: null,
       
    47 
       
    48     /**
       
    49     * Stored reference to the click event binding of the `Select Files`
       
    50     * button.
       
    51     *
       
    52     * @property _buttonBinding
       
    53     * @type {EventHandle}
       
    54     * @protected
       
    55     */
       
    56     _buttonBinding: null,
       
    57 
       
    58     /**
       
    59     * Stored reference to the instance of Uploader.Queue used to manage
       
    60     * the upload process. This is a read-only property that only exists
       
    61     * during an active upload process. Only one queue can be active at
       
    62     * a time; if an upload start is attempted while a queue is active,
       
    63     * it will be ignored.
       
    64     *
       
    65     * @property queue
       
    66     * @type {Y.Uploader.Queue}
       
    67     */
       
    68     queue: null,
       
    69 
       
    70     // Y.UploaderHTML5 prototype
       
    71 
       
    72     /**
       
    73     * Construction logic executed during UploaderHTML5 instantiation.
       
    74     *
       
    75     * @method initializer
       
    76     * @protected
       
    77     */
       
    78     initializer : function () {
       
    79 
       
    80         this._fileInputField = null;
       
    81         this.queue = null;
       
    82         this._buttonBinding = null;
       
    83         this._fileList = [];
       
    84 
       
    85         // Publish available events
       
    86 
       
    87         /**
       
    88         * Signals that files have been selected.
       
    89         *
       
    90         * @event fileselect
       
    91         * @param event {Event} The event object for the `fileselect` with the
       
    92         *                      following payload:
       
    93         *  <dl>
       
    94         *      <dt>fileList</dt>
       
    95         *          <dd>An `Array` of files selected by the user, encapsulated
       
    96         *              in Y.FileHTML5 objects.</dd>
       
    97         *  </dl>
       
    98         */
       
    99         this.publish("fileselect");
       
   100 
       
   101         /**
       
   102         * Signals that an upload of multiple files has been started.
       
   103         *
       
   104         * @event uploadstart
       
   105         * @param event {Event} The event object for the `uploadstart`.
       
   106         */
       
   107         this.publish("uploadstart");
       
   108 
       
   109         /**
       
   110         * Signals that an upload of a specific file has started.
       
   111         *
       
   112         * @event fileuploadstart
       
   113         * @param event {Event} The event object for the `fileuploadstart` with the
       
   114         *                      following payload:
       
   115         *  <dl>
       
   116         *      <dt>file</dt>
       
   117         *          <dd>A reference to the Y.File that dispatched the event.</dd>
       
   118         *      <dt>originEvent</dt>
       
   119         *          <dd>The original event dispatched by Y.File.</dd>
       
   120         *  </dl>
       
   121         */
       
   122         this.publish("fileuploadstart");
       
   123 
       
   124         /**
       
   125         * Reports on upload progress of a specific file.
       
   126         *
       
   127         * @event uploadprogress
       
   128         * @param event {Event} The event object for the `uploadprogress` with the
       
   129         *                      following payload:
       
   130         *  <dl>
       
   131         *      <dt>file</dt>
       
   132         *          <dd>The pointer to the instance of `Y.File` that dispatched the event.</dd>
       
   133         *      <dt>bytesLoaded</dt>
       
   134         *          <dd>The number of bytes of the file that has been uploaded</dd>
       
   135         *      <dt>bytesTotal</dt>
       
   136         *          <dd>The total number of bytes in the file</dd>
       
   137         *      <dt>percentLoaded</dt>
       
   138         *          <dd>The fraction of the file that has been uploaded, out of 100</dd>
       
   139         *      <dt>originEvent</dt>
       
   140         *          <dd>The original event dispatched by the HTML5 uploader</dd>
       
   141         *  </dl>
       
   142         */
       
   143         this.publish("uploadprogress");
       
   144 
       
   145         /**
       
   146         * Reports on the total upload progress of the file list.
       
   147         *
       
   148         * @event totaluploadprogress
       
   149         * @param event {Event} The event object for the `totaluploadprogress` with the
       
   150         *                      following payload:
       
   151         *  <dl>
       
   152         *      <dt>bytesLoaded</dt>
       
   153         *          <dd>The number of bytes of the file list that has been uploaded</dd>
       
   154         *      <dt>bytesTotal</dt>
       
   155         *          <dd>The total number of bytes in the file list</dd>
       
   156         *      <dt>percentLoaded</dt>
       
   157         *          <dd>The fraction of the file list that has been uploaded, out of 100</dd>
       
   158         *  </dl>
       
   159         */
       
   160         this.publish("totaluploadprogress");
       
   161 
       
   162         /**
       
   163         * Signals that a single file upload has been completed.
       
   164         *
       
   165         * @event uploadcomplete
       
   166         * @param event {Event} The event object for the `uploadcomplete` with the
       
   167         *                      following payload:
       
   168         *  <dl>
       
   169         *      <dt>file</dt>
       
   170         *          <dd>The pointer to the instance of `Y.File` whose upload has been completed.</dd>
       
   171         *      <dt>originEvent</dt>
       
   172         *          <dd>The original event fired by the SWF Uploader</dd>
       
   173         *      <dt>data</dt>
       
   174         *          <dd>Data returned by the server.</dd>
       
   175         *  </dl>
       
   176         */
       
   177         this.publish("uploadcomplete");
       
   178 
       
   179         /**
       
   180         * Signals that the upload process of the entire file list has been completed.
       
   181         *
       
   182         * @event alluploadscomplete
       
   183         * @param event {Event} The event object for the `alluploadscomplete`.
       
   184         */
       
   185         this.publish("alluploadscomplete");
       
   186 
       
   187         /**
       
   188         * Signals that a error has occurred in a specific file's upload process.
       
   189         *
       
   190         * @event uploaderror
       
   191         * @param event {Event} The event object for the `uploaderror` with the
       
   192         *                      following payload:
       
   193         *  <dl>
       
   194         *      <dt>originEvent</dt>
       
   195         *          <dd>The original error event fired by the HTML5 Uploader. </dd>
       
   196         *      <dt>file</dt>
       
   197         *          <dd>The pointer at the instance of Y.File that returned the error.</dd>
       
   198         *      <dt>status</dt>
       
   199         *          <dd>The status reported by the XMLHttpRequest object.</dd>
       
   200         *      <dt>statusText</dt>
       
   201         *          <dd>The statusText reported by the XMLHttpRequest object.</dd>
       
   202         *  </dl>
       
   203         */
       
   204         this.publish("uploaderror");
       
   205 
       
   206         /**
       
   207         * Signals that a dragged object has entered into the uploader's associated drag-and-drop area.
       
   208         *
       
   209         * @event dragenter
       
   210         * @param event {Event} The event object for the `dragenter`.
       
   211         */
       
   212         this.publish("dragenter");
       
   213 
       
   214         /**
       
   215         * Signals that an object has been dragged over the uploader's associated drag-and-drop area.
       
   216         *
       
   217         * @event dragover
       
   218         * @param event {Event} The event object for the `dragover`.
       
   219         */
       
   220         this.publish("dragover");
       
   221 
       
   222         /**
       
   223         * Signals that an object has been dragged off of the uploader's associated drag-and-drop area.
       
   224         *
       
   225         * @event dragleave
       
   226         * @param event {Event} The event object for the `dragleave`.
       
   227         */
       
   228         this.publish("dragleave");
       
   229 
       
   230         /**
       
   231         * Signals that an object has been dropped over the uploader's associated drag-and-drop area.
       
   232         *
       
   233         * @event drop
       
   234         * @param event {Event} The event object for the `drop` with the
       
   235         *                      following payload:
       
   236         *  <dl>
       
   237         *      <dt>fileList</dt>
       
   238         *          <dd>An `Array` of files dropped by the user, encapsulated
       
   239         *              in Y.FileHTML5 objects.</dd>
       
   240         *  </dl>
       
   241         */
       
   242         this.publish("drop");
       
   243 
       
   244     },
       
   245 
       
   246     /**
       
   247     * Create the DOM structure for the UploaderHTML5.
       
   248     * UploaderHTML5's DOM structure consists of a "Select Files" button that can
       
   249     * be replaced by the developer's widget of choice; and a hidden file input field
       
   250     * that is used to instantiate the File Select dialog.
       
   251     *
       
   252     * @method renderUI
       
   253     * @protected
       
   254     */
       
   255     renderUI : function () {
       
   256         var contentBox = this.get('contentBox'),
       
   257             selButton = this.get("selectFilesButton");
       
   258 
       
   259         selButton.setStyles({width:"100%", height:"100%"});
       
   260         contentBox.append(selButton);
       
   261         this._fileInputField = Y.Node.create(UploaderHTML5.HTML5FILEFIELD_TEMPLATE);
       
   262         contentBox.append(this._fileInputField);
       
   263     },
       
   264 
       
   265     /**
       
   266     * Binds to the UploaderHTML5 UI and subscribes to the necessary events.
       
   267     *
       
   268     * @method bindUI
       
   269     * @protected
       
   270     */
       
   271     bindUI : function () {
       
   272 
       
   273         this._bindSelectButton();
       
   274         this._setMultipleFiles();
       
   275         this._setFileFilters();
       
   276         this._bindDropArea();
       
   277         this._triggerEnabled();
       
   278 
       
   279         this.after("multipleFilesChange", this._setMultipleFiles, this);
       
   280         this.after("fileFiltersChange", this._setFileFilters, this);
       
   281         this.after("enabledChange", this._triggerEnabled, this);
       
   282         this.after("selectFilesButtonChange", this._bindSelectButton, this);
       
   283         this.after("dragAndDropAreaChange", this._bindDropArea, this);
       
   284         this.after("tabIndexChange", function () {
       
   285             this.get("selectFilesButton").set("tabIndex", this.get("tabIndex"));
       
   286         }, this);
       
   287         this._fileInputField.on("change", this._updateFileList, this);
       
   288 
       
   289         this.get("selectFilesButton").set("tabIndex", this.get("tabIndex"));
       
   290     },
       
   291 
       
   292 
       
   293     /**
       
   294     * Recreates the file field to null out the previous list of files and
       
   295     * thus allow for an identical file list selection.
       
   296     *
       
   297     * @method _rebindFileField
       
   298     * @protected
       
   299     */
       
   300     _rebindFileField : function () {
       
   301         this._fileInputField.remove(true);
       
   302         this._fileInputField = Y.Node.create(UploaderHTML5.HTML5FILEFIELD_TEMPLATE);
       
   303         this.get("contentBox").append(this._fileInputField);
       
   304         this._fileInputField.on("change", this._updateFileList, this);
       
   305         this._setMultipleFiles();
       
   306         this._setFileFilters();
       
   307     },
       
   308 
       
   309 
       
   310     /**
       
   311     * Binds the specified drop area's drag and drop events to the
       
   312     * uploader's custom handler.
       
   313     *
       
   314     * @method _bindDropArea
       
   315     * @protected
       
   316     */
       
   317     _bindDropArea : function (event) {
       
   318         var ev = event || {prevVal: null},
       
   319             ddArea = this.get("dragAndDropArea");
       
   320 
       
   321         if (ev.prevVal !== null) {
       
   322             ev.prevVal.detach('drop', this._ddEventHandler);
       
   323             ev.prevVal.detach('dragenter', this._ddEventHandler);
       
   324             ev.prevVal.detach('dragover', this._ddEventHandler);
       
   325             ev.prevVal.detach('dragleave', this._ddEventHandler);
       
   326         }
       
   327 
       
   328         if (ddArea !== null) {
       
   329             ddArea.on('drop', this._ddEventHandler, this);
       
   330             ddArea.on('dragenter', this._ddEventHandler, this);
       
   331             ddArea.on('dragover', this._ddEventHandler, this);
       
   332             ddArea.on('dragleave', this._ddEventHandler, this);
       
   333         }
       
   334     },
       
   335 
       
   336     /**
       
   337     * Binds the instantiation of the file select dialog to the current file select
       
   338     * control.
       
   339     *
       
   340     * @method _bindSelectButton
       
   341     * @protected
       
   342     */
       
   343     _bindSelectButton : function () {
       
   344        this._buttonBinding = this.get("selectFilesButton").on("click", this.openFileSelectDialog, this);
       
   345     },
       
   346 
       
   347     /**
       
   348     * Handles the drag and drop events from the uploader's specified drop
       
   349     * area.
       
   350     *
       
   351     * @method _ddEventHandler
       
   352     * @protected
       
   353     */
       
   354     _ddEventHandler : function (event) {
       
   355 
       
   356 
       
   357         event.stopPropagation();
       
   358         event.preventDefault();
       
   359 
       
   360         if (Y.Array.indexOf(event._event.dataTransfer.types, 'Files') > -1) {
       
   361             switch (event.type) {
       
   362                 case "dragenter":
       
   363                     this.fire("dragenter");
       
   364                     break;
       
   365                 case "dragover":
       
   366                     this.fire("dragover");
       
   367                     break;
       
   368                 case "dragleave":
       
   369                     this.fire("dragleave");
       
   370                     break;
       
   371                 case "drop":
       
   372 
       
   373                     var newfiles = event._event.dataTransfer.files,
       
   374                         parsedFiles = [],
       
   375                         filterFunc = this.get("fileFilterFunction"),
       
   376                         oldfiles;
       
   377 
       
   378                     if (filterFunc) {
       
   379                         Y.each(newfiles, function (value) {
       
   380                             var newfile = new Y.FileHTML5(value);
       
   381                             if (filterFunc(newfile)) {
       
   382                                 parsedFiles.push(newfile);
       
   383                             }
       
   384                         });
       
   385                     }
       
   386                     else {
       
   387                         Y.each(newfiles, function (value) {
       
   388                             parsedFiles.push(new Y.FileHTML5(value));
       
   389                         });
       
   390                     }
       
   391 
       
   392                     if (parsedFiles.length > 0) {
       
   393                         oldfiles = this.get("fileList");
       
   394                         this.set("fileList",
       
   395                         this.get("appendNewFiles") ? oldfiles.concat(parsedFiles) : parsedFiles);
       
   396                         this.fire("fileselect", {fileList: parsedFiles});
       
   397                     }
       
   398 
       
   399                     this.fire("drop", {fileList: parsedFiles});
       
   400                     break;
       
   401             }
       
   402         }
       
   403     },
       
   404 
       
   405     /**
       
   406     * Adds or removes a specified state CSS class to the underlying uploader button.
       
   407     *
       
   408     * @method _setButtonClass
       
   409     * @protected
       
   410     * @param state {String} The name of the state enumerated in `buttonClassNames` attribute
       
   411     * from which to derive the needed class name.
       
   412     * @param add {Boolean} A Boolean indicating whether to add or remove the class.
       
   413     */
       
   414     _setButtonClass : function (state, add) {
       
   415         if (add) {
       
   416             this.get("selectFilesButton").addClass(this.get("buttonClassNames")[state]);
       
   417         }
       
   418         else {
       
   419             this.get("selectFilesButton").removeClass(this.get("buttonClassNames")[state]);
       
   420         }
       
   421     },
       
   422 
       
   423     /**
       
   424     * Syncs the state of the `multipleFiles` attribute between this class
       
   425     * and the file input field.
       
   426     *
       
   427     * @method _setMultipleFiles
       
   428     * @protected
       
   429     */
       
   430     _setMultipleFiles : function () {
       
   431         if (this.get("multipleFiles") === true) {
       
   432             this._fileInputField.set("multiple", "multiple");
       
   433         }
       
   434         else {
       
   435             this._fileInputField.set("multiple", "");
       
   436         }
       
   437     },
       
   438 
       
   439     /**
       
   440     * Syncs the state of the `fileFilters` attribute between this class
       
   441     * and the file input field.
       
   442     *
       
   443     * @method _setFileFilters
       
   444     * @protected
       
   445     */
       
   446     _setFileFilters : function () {
       
   447         if (this.get("fileFilters").length > 0) {
       
   448             this._fileInputField.set("accept", this.get("fileFilters").join(","));
       
   449         }
       
   450         else {
       
   451             this._fileInputField.set("accept", "");
       
   452         }
       
   453     },
       
   454 
       
   455 
       
   456     /**
       
   457     * Syncs the state of the `enabled` attribute between this class
       
   458     * and the underlying button.
       
   459     *
       
   460     * @method _triggerEnabled
       
   461     * @private
       
   462     */
       
   463     _triggerEnabled : function () {
       
   464         if (this.get("enabled") && this._buttonBinding === null) {
       
   465             this._bindSelectButton();
       
   466             this._setButtonClass("disabled", false);
       
   467             this.get("selectFilesButton").setAttribute("aria-disabled", "false");
       
   468         }
       
   469         else if (!this.get("enabled") && this._buttonBinding) {
       
   470             this._buttonBinding.detach();
       
   471             this._buttonBinding = null;
       
   472             this._setButtonClass("disabled", true);
       
   473             this.get("selectFilesButton").setAttribute("aria-disabled", "true");
       
   474         }
       
   475     },
       
   476 
       
   477     /**
       
   478     * Getter for the `fileList` attribute
       
   479     *
       
   480     * @method _getFileList
       
   481     * @private
       
   482     */
       
   483     _getFileList : function () {
       
   484         return this._fileList.concat();
       
   485     },
       
   486 
       
   487     /**
       
   488     * Setter for the `fileList` attribute
       
   489     *
       
   490     * @method _setFileList
       
   491     * @private
       
   492     */
       
   493     _setFileList : function (val) {
       
   494         this._fileList = val.concat();
       
   495         return this._fileList.concat();
       
   496     },
       
   497 
       
   498     /**
       
   499     * Adjusts the content of the `fileList` based on the results of file selection
       
   500     * and the `appendNewFiles` attribute. If the `appendNewFiles` attribute is true,
       
   501     * then selected files are appended to the existing list; otherwise, the list is
       
   502     * cleared and populated with the newly selected files.
       
   503     *
       
   504     * @method _updateFileList
       
   505     * @param ev {Event} The file selection event received from the uploader.
       
   506     * @protected
       
   507     */
       
   508     _updateFileList : function (ev) {
       
   509         var newfiles = ev.target.getDOMNode().files,
       
   510             parsedFiles = [],
       
   511             filterFunc = this.get("fileFilterFunction"),
       
   512             oldfiles;
       
   513 
       
   514         if (filterFunc) {
       
   515             Y.each(newfiles, function (value) {
       
   516                 var newfile = new Y.FileHTML5(value);
       
   517                 if (filterFunc(newfile)) {
       
   518                     parsedFiles.push(newfile);
       
   519                 }
       
   520             });
       
   521         }
       
   522         else {
       
   523             Y.each(newfiles, function (value) {
       
   524                 parsedFiles.push(new Y.FileHTML5(value));
       
   525             });
       
   526         }
       
   527 
       
   528         if (parsedFiles.length > 0) {
       
   529             oldfiles = this.get("fileList");
       
   530 
       
   531             this.set("fileList",
       
   532                     this.get("appendNewFiles") ? oldfiles.concat(parsedFiles) : parsedFiles );
       
   533 
       
   534             this.fire("fileselect", {fileList: parsedFiles});
       
   535         }
       
   536 
       
   537         this._rebindFileField();
       
   538     },
       
   539 
       
   540 
       
   541     /**
       
   542     * Handles and retransmits events fired by `Y.File` and `Y.Uploader.Queue`.
       
   543     *
       
   544     * @method _uploadEventHandler
       
   545     * @param event The event dispatched during the upload process.
       
   546     * @protected
       
   547     */
       
   548     _uploadEventHandler : function (event) {
       
   549 
       
   550         switch (event.type) {
       
   551             case "file:uploadstart":
       
   552                 this.fire("fileuploadstart", event);
       
   553                 break;
       
   554             case "file:uploadprogress":
       
   555                 this.fire("uploadprogress", event);
       
   556                 break;
       
   557             case "uploaderqueue:totaluploadprogress":
       
   558                 this.fire("totaluploadprogress", event);
       
   559                 break;
       
   560             case "file:uploadcomplete":
       
   561                 this.fire("uploadcomplete", event);
       
   562                 break;
       
   563             case "uploaderqueue:alluploadscomplete":
       
   564                 this.queue = null;
       
   565                 this.fire("alluploadscomplete", event);
       
   566                 break;
       
   567             case "file:uploaderror": // overflow intentional
       
   568             case "uploaderqueue:uploaderror":
       
   569                 this.fire("uploaderror", event);
       
   570                 break;
       
   571             case "file:uploadcancel": // overflow intentional
       
   572             case "uploaderqueue:uploadcancel":
       
   573                 this.fire("uploadcancel", event);
       
   574                 break;
       
   575         }
       
   576 
       
   577     },
       
   578 
       
   579     /**
       
   580     * Opens the File Selection dialog by simulating a click on the file input field.
       
   581     *
       
   582     * @method openFileSelectDialog
       
   583     */
       
   584     openFileSelectDialog : function () {
       
   585         var fileDomNode = this._fileInputField.getDOMNode();
       
   586         if (fileDomNode.click) {
       
   587             fileDomNode.click();
       
   588         }
       
   589     },
       
   590 
       
   591     /**
       
   592     * Starts the upload of a specific file.
       
   593     *
       
   594     * @method upload
       
   595     * @param file {Y.File} Reference to the instance of the file to be uploaded.
       
   596     * @param url {String} The URL to upload the file to.
       
   597     * @param postVars {Object} (optional) A set of key-value pairs to send as variables along with the file upload HTTP request.
       
   598     *                          If not specified, the values from the attribute `postVarsPerFile` are used instead.
       
   599     */
       
   600     upload : function (file, url, postvars) {
       
   601 
       
   602         var uploadURL = url || this.get("uploadURL"),
       
   603             postVars = postvars || this.get("postVarsPerFile"),
       
   604             fileId = file.get("id");
       
   605 
       
   606         postVars = postVars.hasOwnProperty(fileId) ? postVars[fileId] : postVars;
       
   607 
       
   608         if (file instanceof Y.FileHTML5) {
       
   609 
       
   610             file.on("uploadstart", this._uploadEventHandler, this);
       
   611             file.on("uploadprogress", this._uploadEventHandler, this);
       
   612             file.on("uploadcomplete", this._uploadEventHandler, this);
       
   613             file.on("uploaderror", this._uploadEventHandler, this);
       
   614             file.on("uploadcancel", this._uploadEventHandler, this);
       
   615 
       
   616             file.startUpload(uploadURL, postVars, this.get("fileFieldName"));
       
   617         }
       
   618     },
       
   619 
       
   620    /**
       
   621     * Starts the upload of all files on the file list, using an automated queue.
       
   622     *
       
   623     * @method uploadAll
       
   624     * @param url {String} The URL to upload the files to.
       
   625     * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request.
       
   626     *                          If not specified, the values from the attribute `postVarsPerFile` are used instead.
       
   627     */
       
   628     uploadAll : function (url, postvars) {
       
   629         this.uploadThese(this.get("fileList"), url, postvars);
       
   630     },
       
   631 
       
   632     /**
       
   633     * Starts the upload of the files specified in the first argument, using an automated queue.
       
   634     *
       
   635     * @method uploadThese
       
   636     * @param files {Array} The list of files to upload.
       
   637     * @param url {String} The URL to upload the files to.
       
   638     * @param [postVars] {Object} A set of key-value pairs to send as variables along with the file upload HTTP request.
       
   639     *                          If not specified, the values from the attribute `postVarsPerFile` are used instead.
       
   640     */
       
   641     uploadThese : function (files, url, postvars) {
       
   642         if (!this.queue) {
       
   643             var uploadURL = url || this.get("uploadURL"),
       
   644                 postVars = postvars || this.get("postVarsPerFile");
       
   645 
       
   646             this.queue = new UploaderQueue({
       
   647                 simUploads: this.get("simLimit"),
       
   648                 errorAction: this.get("errorAction"),
       
   649                 fileFieldName: this.get("fileFieldName"),
       
   650                 fileList: files,
       
   651                 uploadURL: uploadURL,
       
   652                 perFileParameters: postVars,
       
   653                 retryCount: this.get("retryCount"),
       
   654                 uploadHeaders: this.get("uploadHeaders"),
       
   655                 withCredentials: this.get("withCredentials")
       
   656             });
       
   657 
       
   658             this.queue.on("uploadstart", this._uploadEventHandler, this);
       
   659             this.queue.on("uploadprogress", this._uploadEventHandler, this);
       
   660             this.queue.on("totaluploadprogress", this._uploadEventHandler, this);
       
   661             this.queue.on("uploadcomplete", this._uploadEventHandler, this);
       
   662             this.queue.on("alluploadscomplete", this._uploadEventHandler, this);
       
   663             this.queue.on("uploadcancel", this._uploadEventHandler, this);
       
   664             this.queue.on("uploaderror", this._uploadEventHandler, this);
       
   665             this.queue.startUpload();
       
   666 
       
   667             this.fire("uploadstart");
       
   668        }
       
   669        else if (this.queue._currentState === UploaderQueue.UPLOADING) {
       
   670             this.queue.set("perFileParameters", this.get("postVarsPerFile"));
       
   671             Y.each(files, function (file) {
       
   672                 this.queue.addToQueueBottom(file);
       
   673             }, this);
       
   674        }
       
   675     }
       
   676 }, {
       
   677 
       
   678     /**
       
   679     * The template for the hidden file input field container. The file input field will only
       
   680     * accept clicks if its visibility is set to hidden (and will not if it's `display` value
       
   681     * is set to `none`)
       
   682     *
       
   683     * @property HTML5FILEFIELD_TEMPLATE
       
   684     * @type {String}
       
   685     * @static
       
   686     */
       
   687     HTML5FILEFIELD_TEMPLATE: "<input type='file' style='visibility:hidden; width:0px; height: 0px;'>",
       
   688 
       
   689     /**
       
   690     * The template for the "Select Files" button.
       
   691     *
       
   692     * @property SELECT_FILES_BUTTON
       
   693     * @type {HTML}
       
   694     * @static
       
   695     * @default '<button type="button" class="yui3-button" role="button" aria-label="{selectButtonLabel}"
       
   696     *           tabindex="{tabIndex}">{selectButtonLabel}</button>'
       
   697     */
       
   698     SELECT_FILES_BUTTON: '<button type="button" class="yui3-button" role="button" aria-label="{selectButtonLabel}" ' +
       
   699                          'tabindex="{tabIndex}">{selectButtonLabel}</button>',
       
   700 
       
   701     /**
       
   702     * The static property reflecting the type of uploader that `Y.Uploader`
       
   703     * aliases. The UploaderHTML5 value is `"html5"`.
       
   704     *
       
   705     * @property TYPE
       
   706     * @type {String}
       
   707     * @static
       
   708     */
       
   709     TYPE: "html5",
       
   710 
       
   711     /**
       
   712     * The identity of the widget.
       
   713     *
       
   714     * @property NAME
       
   715     * @type String
       
   716     * @default 'uploader'
       
   717     * @readOnly
       
   718     * @protected
       
   719     * @static
       
   720     */
       
   721     NAME: "uploader",
       
   722 
       
   723     /**
       
   724     * Static property used to define the default attribute configuration of
       
   725     * the Widget.
       
   726     *
       
   727     * @property ATTRS
       
   728     * @type {Object}
       
   729     * @protected
       
   730     * @static
       
   731     */
       
   732     ATTRS: {
       
   733 
       
   734         /**
       
   735         * A Boolean indicating whether newly selected files should be appended
       
   736         * to the existing file list, or whether they should replace it.
       
   737         *
       
   738         * @attribute appendNewFiles
       
   739         * @type {Boolean}
       
   740         * @default true
       
   741         */
       
   742         appendNewFiles : {
       
   743             value: true
       
   744         },
       
   745 
       
   746         /**
       
   747         * The names of CSS classes that correspond to different button states
       
   748         * of the "Select Files" control. These classes are assigned to the
       
   749         * "Select Files" control based on the configuration of the uploader.
       
   750         * Currently, the only class name used is that corresponding to the
       
   751         * `disabled` state of the uploader. Other button states should be managed
       
   752         * directly via CSS selectors.
       
   753         * <ul>
       
   754         *   <li> <strong>`disabled`</strong>: the class corresponding to the disabled state
       
   755         *      of the "Select Files" button.</li>
       
   756         * </ul>
       
   757         * @attribute buttonClassNames
       
   758         * @type {Object}
       
   759         * @default {
       
   760         *            disabled: "yui3-button-disabled"
       
   761         *          }
       
   762         */
       
   763         buttonClassNames: {
       
   764             value: {
       
   765                 "hover": "yui3-button-hover",
       
   766                 "active": "yui3-button-active",
       
   767                 "disabled": "yui3-button-disabled",
       
   768                 "focus": "yui3-button-selected"
       
   769             }
       
   770         },
       
   771 
       
   772         /**
       
   773         * The node that serves as the drop target for files.
       
   774         *
       
   775         * @attribute dragAndDropArea
       
   776         * @type {Node}
       
   777         * @default null
       
   778         */
       
   779         dragAndDropArea: {
       
   780             value: null,
       
   781             setter: function (val) {
       
   782                 return Y.one(val);
       
   783             }
       
   784         },
       
   785 
       
   786         /**
       
   787         * A Boolean indicating whether the uploader is enabled or disabled for user input.
       
   788         *
       
   789         * @attribute enabled
       
   790         * @type {Boolean}
       
   791         * @default true
       
   792         */
       
   793         enabled : {
       
   794             value: true
       
   795         },
       
   796 
       
   797         /**
       
   798         * The action  performed when an upload error occurs for a specific file being uploaded.
       
   799         * The possible values are:
       
   800         * <ul>
       
   801         *   <li> <strong>`UploaderQueue.CONTINUE`</strong>: the error is ignored and the upload process is continued.</li>
       
   802         *   <li> <strong>`UploaderQueue.STOP`</strong>: the upload process is stopped as soon as any other parallel file
       
   803         *     uploads are finished.</li>
       
   804         *   <li> <strong>`UploaderQueue.RESTART_ASAP`</strong>: the file is added back to the front of the queue.</li>
       
   805         *   <li> <strong>`UploaderQueue.RESTART_AFTER`</strong>: the file is added to the back of the queue.</li>
       
   806         * </ul>
       
   807         * @attribute errorAction
       
   808         * @type {String}
       
   809         * @default UploaderQueue.CONTINUE
       
   810         */
       
   811         errorAction: {
       
   812             value: "continue",
       
   813             validator: function (val) {
       
   814                 return (
       
   815                     val === UploaderQueue.CONTINUE ||
       
   816                     val === UploaderQueue.STOP ||
       
   817                     val === UploaderQueue.RESTART_ASAP ||
       
   818                     val === UploaderQueue.RESTART_AFTER
       
   819                 );
       
   820             }
       
   821         },
       
   822 
       
   823         /**
       
   824         * An array indicating what fileFilters should be applied to the file
       
   825         * selection dialog. Each element in the array should be a string
       
   826         * indicating the Media (MIME) type for the files that should be supported
       
   827         * for selection. The Media type strings should be properly formatted
       
   828         * or this parameter will be ignored. Examples of valid strings include:
       
   829         * "audio/*", "video/*", "application/pdf", etc. More information
       
   830         * on valid Media type strings is available here:
       
   831         * http://www.iana.org/assignments/media-types/index.html
       
   832         * @attribute fileFilters
       
   833         * @type {Array}
       
   834         * @default []
       
   835         */
       
   836         fileFilters: {
       
   837             value: []
       
   838         },
       
   839 
       
   840         /**
       
   841         * A filtering function that is applied to every file selected by the user.
       
   842         * The function receives the `Y.File` object and must return a Boolean value.
       
   843         * If a `false` value is returned, the file in question is not added to the
       
   844         * list of files to be uploaded.
       
   845         * Use this function to put limits on file sizes or check the file names for
       
   846         * correct extension, but make sure that a server-side check is also performed,
       
   847         * since any client-side restrictions are only advisory and can be circumvented.
       
   848         *
       
   849         * @attribute fileFilterFunction
       
   850         * @type {Function}
       
   851         * @default null
       
   852         */
       
   853         fileFilterFunction: {
       
   854             value: null
       
   855         },
       
   856 
       
   857         /**
       
   858         * A String specifying what should be the POST field name for the file
       
   859         * content in the upload request.
       
   860         *
       
   861         * @attribute fileFieldName
       
   862         * @type {String}
       
   863         * @default Filedata
       
   864         */
       
   865         fileFieldName: {
       
   866             value: "Filedata"
       
   867         },
       
   868 
       
   869         /**
       
   870         * The array of files to be uploaded. All elements in the array
       
   871         * must be instances of `Y.File` and be instantiated with an instance
       
   872         * of native JavaScript File() class.
       
   873         *
       
   874         * @attribute fileList
       
   875         * @type {Array}
       
   876         * @default []
       
   877         */
       
   878         fileList: {
       
   879             value: [],
       
   880             getter: "_getFileList",
       
   881             setter: "_setFileList"
       
   882         },
       
   883 
       
   884         /**
       
   885         * A Boolean indicating whether multiple file selection is enabled.
       
   886         *
       
   887         * @attribute multipleFiles
       
   888         * @type {Boolean}
       
   889         * @default false
       
   890         */
       
   891         multipleFiles: {
       
   892             value: false
       
   893         },
       
   894 
       
   895         /**
       
   896         * An object, keyed by `fileId`, containing sets of key-value pairs
       
   897         * that should be passed as POST variables along with each corresponding
       
   898         * file. This attribute is only used if no POST variables are specifed
       
   899         * in the upload method call.
       
   900         *
       
   901         * @attribute postVarsPerFile
       
   902         * @type {Object}
       
   903         * @default {}
       
   904         */
       
   905         postVarsPerFile: {
       
   906             value: {}
       
   907         },
       
   908 
       
   909         /**
       
   910         * The label for the "Select Files" widget. This is the value that replaces the
       
   911         * `{selectButtonLabel}` token in the `SELECT_FILES_BUTTON` template.
       
   912         *
       
   913         * @attribute selectButtonLabel
       
   914         * @type {String}
       
   915         * @default "Select Files"
       
   916         */
       
   917         selectButtonLabel: {
       
   918             value: "Select Files"
       
   919         },
       
   920 
       
   921         /**
       
   922         * The widget that serves as the "Select Files control for the file uploader
       
   923         *
       
   924         *
       
   925         * @attribute selectFilesButton
       
   926         * @type {Node | Widget}
       
   927         * @default A standard HTML button with YUI CSS Button skin.
       
   928         */
       
   929         selectFilesButton : {
       
   930             valueFn: function () {
       
   931                 return Y.Node.create(substitute(Y.UploaderHTML5.SELECT_FILES_BUTTON, {
       
   932                     selectButtonLabel: this.get("selectButtonLabel"),
       
   933                     tabIndex: this.get("tabIndex")
       
   934                 }));
       
   935             }
       
   936         },
       
   937 
       
   938         /**
       
   939         * The number of files that can be uploaded
       
   940         * simultaneously if the automatic queue management
       
   941         * is used. This value can be in the range between 2
       
   942         * and 5.
       
   943         *
       
   944         * @attribute simLimit
       
   945         * @type {Number}
       
   946         * @default 2
       
   947         */
       
   948         simLimit: {
       
   949             value: 2,
       
   950             validator: function (val) {
       
   951                 return (val >= 1 && val <= 5);
       
   952             }
       
   953         },
       
   954 
       
   955         /**
       
   956         * The URL to which file upload requested are POSTed. Only used if a different url is not passed to the upload method call.
       
   957         *
       
   958         * @attribute uploadURL
       
   959         * @type {String}
       
   960         * @default ""
       
   961         */
       
   962         uploadURL: {
       
   963             value: ""
       
   964         },
       
   965 
       
   966         /**
       
   967         * Additional HTTP headers that should be included
       
   968         * in the upload request.
       
   969         *
       
   970         *
       
   971         * @attribute uploadHeaders
       
   972         * @type {Object}
       
   973         * @default {}
       
   974         */
       
   975         uploadHeaders: {
       
   976             value: {}
       
   977         },
       
   978 
       
   979         /**
       
   980         * A Boolean that specifies whether the file should be
       
   981         * uploaded with the appropriate user credentials for the
       
   982         * domain.
       
   983         *
       
   984         * @attribute withCredentials
       
   985         * @type {Boolean}
       
   986         * @default true
       
   987         */
       
   988         withCredentials: {
       
   989             value: true
       
   990         },
       
   991 
       
   992         /**
       
   993         * The number of times to try re-uploading a file that failed to upload before
       
   994         * cancelling its upload.
       
   995         *
       
   996         * @attribute retryCount
       
   997         * @type {Number}
       
   998         * @default 3
       
   999         */
       
  1000         retryCount: {
       
  1001             value: 3
       
  1002         }
       
  1003     }
       
  1004 });
       
  1005 
       
  1006 Y.UploaderHTML5.Queue = UploaderQueue;
       
  1007 
       
  1008 
       
  1009 
       
  1010 }, '3.10.3', {"requires": ["widget", "node-event-simulate", "file-html5", "uploader-queue"]});