src/cm/media/js/lib/yui/yui3-3.15.0/build/uploader-queue/uploader-queue.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('uploader-queue', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4 * The class manages a queue of files that should be uploaded to the server.
       
     5 * It initializes the required number of uploads, tracks them as they progress,
       
     6 * and automatically advances to the next upload when a preceding one has completed.
       
     7 * @module uploader-queue
       
     8 */
       
     9 
       
    10 
       
    11 
       
    12 /**
       
    13 * This class manages a queue of files to be uploaded to the server.
       
    14 * @class Uploader.Queue
       
    15 * @extends Base
       
    16 * @constructor
       
    17 */
       
    18 var UploaderQueue = function() {
       
    19     this.queuedFiles = [];
       
    20     this.uploadRetries = {};
       
    21     this.numberOfUploads = 0;
       
    22     this.currentUploadedByteValues = {};
       
    23     this.currentFiles = {};
       
    24     this.totalBytesUploaded = 0;
       
    25     this.totalBytes = 0;
       
    26 
       
    27     UploaderQueue.superclass.constructor.apply(this, arguments);
       
    28 };
       
    29 
       
    30 
       
    31 Y.extend(UploaderQueue, Y.Base, {
       
    32 
       
    33     /**
       
    34     * Stored value of the current queue state
       
    35     * @property _currentState
       
    36     * @type {String}
       
    37     * @protected
       
    38     * @default UploaderQueue.STOPPED
       
    39     */
       
    40     _currentState: UploaderQueue.STOPPED,
       
    41 
       
    42     /**
       
    43     * Construction logic executed during UploaderQueue instantiation.
       
    44     *
       
    45     * @method initializer
       
    46     * @protected
       
    47     */
       
    48     initializer : function () {},
       
    49 
       
    50     /**
       
    51     * Handles and retransmits upload start event.
       
    52     *
       
    53     * @method _uploadStartHandler
       
    54     * @param event The event dispatched during the upload process.
       
    55     * @private
       
    56     */
       
    57     _uploadStartHandler : function (event) {
       
    58         var updatedEvent = event;
       
    59         updatedEvent.file = event.target;
       
    60         updatedEvent.originEvent = event;
       
    61 
       
    62         this.fire("uploadstart", updatedEvent);
       
    63     },
       
    64 
       
    65     /**
       
    66     * Handles and retransmits upload error event.
       
    67     *
       
    68     * @method _uploadErrorHandler
       
    69     * @param event The event dispatched during the upload process.
       
    70     * @private
       
    71     */
       
    72     _uploadErrorHandler : function (event) {
       
    73         var errorAction = this.get("errorAction"),
       
    74             updatedEvent = event,
       
    75             fileid,
       
    76             retries;
       
    77 
       
    78         updatedEvent.file = event.target;
       
    79         updatedEvent.originEvent = event;
       
    80 
       
    81         this.numberOfUploads-=1;
       
    82         delete this.currentFiles[event.target.get("id")];
       
    83         this._detachFileEvents(event.target);
       
    84 
       
    85         event.target.cancelUpload();
       
    86 
       
    87         if (errorAction === UploaderQueue.STOP) {
       
    88             this.pauseUpload();
       
    89         }
       
    90 
       
    91         else if (errorAction === UploaderQueue.RESTART_ASAP) {
       
    92             fileid = event.target.get("id");
       
    93             retries = this.uploadRetries[fileid] || 0;
       
    94 
       
    95             if (retries < this.get("retryCount")) {
       
    96                 this.uploadRetries[fileid] = retries + 1;
       
    97                 this.addToQueueTop(event.target);
       
    98             }
       
    99             this._startNextFile();
       
   100         }
       
   101         else if (errorAction === UploaderQueue.RESTART_AFTER) {
       
   102             fileid = event.target.get("id");
       
   103             retries = this.uploadRetries[fileid] || 0;
       
   104 
       
   105             if (retries < this.get("retryCount")) {
       
   106                 this.uploadRetries[fileid] = retries + 1;
       
   107                 this.addToQueueBottom(event.target);
       
   108             }
       
   109             this._startNextFile();
       
   110         }
       
   111 
       
   112         this.fire("uploaderror", updatedEvent);
       
   113     },
       
   114 
       
   115     /**
       
   116     * Launches the upload of the next file in the queue.
       
   117     *
       
   118     * @method _startNextFile
       
   119     * @private
       
   120     */
       
   121     _startNextFile : function () {
       
   122         if (this.queuedFiles.length > 0) {
       
   123             var currentFile = this.queuedFiles.shift(),
       
   124                 fileId = currentFile.get("id"),
       
   125                 parameters = this.get("perFileParameters"),
       
   126                 fileParameters = parameters.hasOwnProperty(fileId) ? parameters[fileId] : parameters;
       
   127 
       
   128             this.currentUploadedByteValues[fileId] = 0;
       
   129 
       
   130             currentFile.on("uploadstart", this._uploadStartHandler, this);
       
   131             currentFile.on("uploadprogress", this._uploadProgressHandler, this);
       
   132             currentFile.on("uploadcomplete", this._uploadCompleteHandler, this);
       
   133             currentFile.on("uploaderror", this._uploadErrorHandler, this);
       
   134             currentFile.on("uploadcancel", this._uploadCancelHandler, this);
       
   135 
       
   136             currentFile.set("xhrHeaders", this.get("uploadHeaders"));
       
   137             currentFile.set("xhrWithCredentials", this.get("withCredentials"));
       
   138 
       
   139             currentFile.startUpload(this.get("uploadURL"), fileParameters, this.get("fileFieldName"));
       
   140 
       
   141             this._registerUpload(currentFile);
       
   142         }
       
   143     },
       
   144 
       
   145     /**
       
   146     * Register a new upload process.
       
   147     *
       
   148     * @method _registerUpload
       
   149     * @private
       
   150     */
       
   151     _registerUpload : function (file) {
       
   152         this.numberOfUploads += 1;
       
   153         this.currentFiles[file.get("id")] = file;
       
   154     },
       
   155 
       
   156     /**
       
   157     * Unregisters a new upload process.
       
   158     *
       
   159     * @method _unregisterUpload
       
   160     * @private
       
   161     */
       
   162     _unregisterUpload : function (file) {
       
   163         if (this.numberOfUploads > 0) {
       
   164             this.numberOfUploads -= 1;
       
   165         }
       
   166 
       
   167         delete this.currentFiles[file.get("id")];
       
   168         delete this.uploadRetries[file.get("id")];
       
   169 
       
   170         this._detachFileEvents(file);
       
   171     },
       
   172 
       
   173     _detachFileEvents : function (file) {
       
   174         file.detach("uploadstart", this._uploadStartHandler);
       
   175         file.detach("uploadprogress", this._uploadProgressHandler);
       
   176         file.detach("uploadcomplete", this._uploadCompleteHandler);
       
   177         file.detach("uploaderror", this._uploadErrorHandler);
       
   178         file.detach("uploadcancel", this._uploadCancelHandler);
       
   179     },
       
   180 
       
   181     /**
       
   182     * Handles and retransmits upload complete event.
       
   183     *
       
   184     * @method _uploadCompleteHandler
       
   185     * @param event The event dispatched during the upload process.
       
   186     * @private
       
   187     */
       
   188     _uploadCompleteHandler : function (event) {
       
   189 
       
   190         this._unregisterUpload(event.target);
       
   191 
       
   192         this.totalBytesUploaded += event.target.get("size");
       
   193         delete this.currentUploadedByteValues[event.target.get("id")];
       
   194 
       
   195 
       
   196         if (this.queuedFiles.length > 0 && this._currentState === UploaderQueue.UPLOADING) {
       
   197             this._startNextFile();
       
   198         }
       
   199 
       
   200         var updatedEvent = event,
       
   201             uploadedTotal = this.totalBytesUploaded,
       
   202             percentLoaded = Math.min(100, Math.round(10000*uploadedTotal/this.totalBytes) / 100);
       
   203 
       
   204         updatedEvent.file = event.target;
       
   205         updatedEvent.originEvent = event;
       
   206 
       
   207         Y.each(this.currentUploadedByteValues, function (value) {
       
   208             uploadedTotal += value;
       
   209         });
       
   210 
       
   211         this.fire("totaluploadprogress", {
       
   212             bytesLoaded: uploadedTotal,
       
   213             bytesTotal: this.totalBytes,
       
   214             percentLoaded: percentLoaded
       
   215         });
       
   216 
       
   217         this.fire("uploadcomplete", updatedEvent);
       
   218 
       
   219         if (this.queuedFiles.length === 0 && this.numberOfUploads <= 0) {
       
   220             this.fire("alluploadscomplete");
       
   221             this._currentState = UploaderQueue.STOPPED;
       
   222         }
       
   223     },
       
   224 
       
   225     /**
       
   226     * Handles and retransmits upload cancel event.
       
   227     *
       
   228     * @method _uploadCancelHandler
       
   229     * @param event The event dispatched during the upload process.
       
   230     * @private
       
   231     */
       
   232     _uploadCancelHandler : function (event) {
       
   233 
       
   234         var updatedEvent = event;
       
   235         updatedEvent.originEvent = event;
       
   236         updatedEvent.file = event.target;
       
   237 
       
   238         this.fire("uploadcancel", updatedEvent);
       
   239     },
       
   240 
       
   241 
       
   242 
       
   243     /**
       
   244     * Handles and retransmits upload progress event.
       
   245     *
       
   246     * @method _uploadProgressHandler
       
   247     * @param event The event dispatched during the upload process.
       
   248     * @private
       
   249     */
       
   250     _uploadProgressHandler : function (event) {
       
   251 
       
   252         this.currentUploadedByteValues[event.target.get("id")] = event.bytesLoaded;
       
   253 
       
   254         var updatedEvent = event,
       
   255             uploadedTotal = this.totalBytesUploaded,
       
   256             percentLoaded = Math.min(100, Math.round(10000*uploadedTotal/this.totalBytes) / 100);
       
   257 
       
   258         updatedEvent.originEvent = event;
       
   259         updatedEvent.file = event.target;
       
   260 
       
   261         this.fire("uploadprogress", updatedEvent);
       
   262 
       
   263         Y.each(this.currentUploadedByteValues, function (value) {
       
   264             uploadedTotal += value;
       
   265         });
       
   266 
       
   267         this.fire("totaluploadprogress", {
       
   268             bytesLoaded: uploadedTotal,
       
   269             bytesTotal: this.totalBytes,
       
   270             percentLoaded: percentLoaded
       
   271         });
       
   272     },
       
   273 
       
   274     /**
       
   275     * Starts uploading the queued up file list.
       
   276     *
       
   277     * @method startUpload
       
   278     */
       
   279     startUpload: function() {
       
   280         this.queuedFiles = this.get("fileList").slice(0);
       
   281         this.numberOfUploads = 0;
       
   282         this.currentUploadedByteValues = {};
       
   283         this.currentFiles = {};
       
   284         this.totalBytesUploaded = 0;
       
   285 
       
   286         this._currentState = UploaderQueue.UPLOADING;
       
   287 
       
   288         while (this.numberOfUploads < this.get("simUploads") && this.queuedFiles.length > 0) {
       
   289             this._startNextFile();
       
   290         }
       
   291     },
       
   292 
       
   293     /**
       
   294     * Pauses the upload process. The ongoing file uploads
       
   295     * will complete after this method is called, but no
       
   296     * new ones will be launched.
       
   297     *
       
   298     * @method pauseUpload
       
   299     */
       
   300     pauseUpload: function () {
       
   301         this._currentState = UploaderQueue.STOPPED;
       
   302     },
       
   303 
       
   304     /**
       
   305     * Restarts a paused upload process.
       
   306     *
       
   307     * @method restartUpload
       
   308     */
       
   309     restartUpload: function () {
       
   310         this._currentState = UploaderQueue.UPLOADING;
       
   311         while (this.numberOfUploads < this.get("simUploads")) {
       
   312              this._startNextFile();
       
   313         }
       
   314     },
       
   315 
       
   316     /**
       
   317     * If a particular file is stuck in an ongoing upload without
       
   318     * any progress events, this method allows to force its reupload
       
   319     * by cancelling its upload and immediately relaunching it.
       
   320     *
       
   321     * @method forceReupload
       
   322     * @param file {File} The file to force reupload on.
       
   323     */
       
   324     forceReupload : function (file) {
       
   325         var id = file.get("id");
       
   326         if (this.currentFiles.hasOwnProperty(id)) {
       
   327             file.cancelUpload();
       
   328             this._unregisterUpload(file);
       
   329             this.addToQueueTop(file);
       
   330             this._startNextFile();
       
   331         }
       
   332     },
       
   333 
       
   334     /**
       
   335     * Add a new file to the top of the queue (the upload will be
       
   336     * launched as soon as the current number of uploading files
       
   337     * drops below the maximum permissible value).
       
   338     *
       
   339     * @method addToQueueTop
       
   340     * @param file {File} The file to add to the top of the queue.
       
   341     */
       
   342     addToQueueTop: function (file) {
       
   343             this.queuedFiles.unshift(file);
       
   344     },
       
   345 
       
   346     /**
       
   347     * Add a new file to the bottom of the queue (the upload will be
       
   348     * launched after all the other queued files are uploaded.)
       
   349     *
       
   350     * @method addToQueueBottom
       
   351     * @param file {File} The file to add to the bottom of the queue.
       
   352     */
       
   353     addToQueueBottom: function (file) {
       
   354             this.queuedFiles.push(file);
       
   355     },
       
   356 
       
   357     /**
       
   358     * Cancels a specific file's upload. If no argument is passed,
       
   359     * all ongoing uploads are cancelled and the upload process is
       
   360     * stopped.
       
   361     *
       
   362     * @method cancelUpload
       
   363     * @param file {File} An optional parameter - the file whose upload
       
   364     * should be cancelled.
       
   365     */
       
   366     cancelUpload: function (file) {
       
   367         var id,
       
   368             i,
       
   369             fid;
       
   370 
       
   371         if (file) {
       
   372             id = file.get("id");
       
   373 
       
   374             if (this.currentFiles[id]) {
       
   375                 this.currentFiles[id].cancelUpload();
       
   376                 this._unregisterUpload(this.currentFiles[id]);
       
   377                 if (this._currentState === UploaderQueue.UPLOADING) {
       
   378                     this._startNextFile();
       
   379                 }
       
   380             }
       
   381             else {
       
   382                 for (i = 0, len = this.queuedFiles.length; i < len; i++) {
       
   383                     if (this.queuedFiles[i].get("id") === id) {
       
   384                         this.queuedFiles.splice(i, 1);
       
   385                         break;
       
   386                     }
       
   387                 }
       
   388             }
       
   389         }
       
   390         else {
       
   391             for (fid in this.currentFiles) {
       
   392                 this.currentFiles[fid].cancelUpload();
       
   393                 this._unregisterUpload(this.currentFiles[fid]);
       
   394             }
       
   395 
       
   396             this.currentUploadedByteValues = {};
       
   397             this.currentFiles = {};
       
   398             this.totalBytesUploaded = 0;
       
   399             this.fire("alluploadscancelled");
       
   400             this._currentState = UploaderQueue.STOPPED;
       
   401         }
       
   402     }
       
   403 }, {
       
   404     /**
       
   405     * Static constant for the value of the `errorAction` attribute:
       
   406     * prescribes the queue to continue uploading files in case of
       
   407     * an error.
       
   408     * @property CONTINUE
       
   409     * @readOnly
       
   410     * @type {String}
       
   411     * @static
       
   412     */
       
   413     CONTINUE: "continue",
       
   414 
       
   415     /**
       
   416     * Static constant for the value of the `errorAction` attribute:
       
   417     * prescribes the queue to stop uploading files in case of
       
   418     * an error.
       
   419     * @property STOP
       
   420     * @readOnly
       
   421     * @type {String}
       
   422     * @static
       
   423     */
       
   424     STOP: "stop",
       
   425 
       
   426     /**
       
   427     * Static constant for the value of the `errorAction` attribute:
       
   428     * prescribes the queue to restart a file upload immediately in case of
       
   429     * an error.
       
   430     * @property RESTART_ASAP
       
   431     * @readOnly
       
   432     * @type {String}
       
   433     * @static
       
   434     */
       
   435     RESTART_ASAP: "restartasap",
       
   436 
       
   437     /**
       
   438     * Static constant for the value of the `errorAction` attribute:
       
   439     * prescribes the queue to restart an errored out file upload after
       
   440     * other files have finished uploading.
       
   441     * @property RESTART_AFTER
       
   442     * @readOnly
       
   443     * @type {String}
       
   444     * @static
       
   445     */
       
   446     RESTART_AFTER: "restartafter",
       
   447 
       
   448     /**
       
   449     * Static constant for the value of the `_currentState` property:
       
   450     * implies that the queue is currently not uploading files.
       
   451     * @property STOPPED
       
   452     * @readOnly
       
   453     * @type {String}
       
   454     * @static
       
   455     */
       
   456     STOPPED: "stopped",
       
   457 
       
   458     /**
       
   459     * Static constant for the value of the `_currentState` property:
       
   460     * implies that the queue is currently uploading files.
       
   461     * @property UPLOADING
       
   462     * @readOnly
       
   463     * @type {String}
       
   464     * @static
       
   465     */
       
   466     UPLOADING: "uploading",
       
   467 
       
   468     /**
       
   469     * The identity of the class.
       
   470     *
       
   471     * @property NAME
       
   472     * @type String
       
   473     * @default 'uploaderqueue'
       
   474     * @readOnly
       
   475     * @protected
       
   476     * @static
       
   477     */
       
   478     NAME: 'uploaderqueue',
       
   479 
       
   480     /**
       
   481     * Static property used to define the default attribute configuration of
       
   482     * the class.
       
   483     *
       
   484     * @property ATTRS
       
   485     * @type {Object}
       
   486     * @protected
       
   487     * @static
       
   488     */
       
   489     ATTRS: {
       
   490 
       
   491         /**
       
   492         * Maximum number of simultaneous uploads; must be in the
       
   493         * range between 1 and 5. The value of `2` is default. It
       
   494         * is recommended that this value does not exceed 3.
       
   495         * @attribute simUploads
       
   496         * @type Number
       
   497         * @default 2
       
   498         */
       
   499          simUploads: {
       
   500                  value: 2,
       
   501                  validator: function (val) {
       
   502                          return (val >= 1 && val <= 5);
       
   503                  }
       
   504          },
       
   505 
       
   506         /**
       
   507         * The action to take in case of error. The valid values for this attribute are:
       
   508         * `Y.Uploader.Queue.CONTINUE` (the upload process should continue on other files,
       
   509         * ignoring the error), `Y.Uploader.Queue.STOP` (the upload process
       
   510         * should stop completely), `Y.Uploader.Queue.RESTART_ASAP` (the upload
       
   511         * should restart immediately on the errored out file and continue as planned), or
       
   512         * Y.Uploader.Queue.RESTART_AFTER (the upload of the errored out file should restart
       
   513         * after all other files have uploaded)
       
   514         * @attribute errorAction
       
   515         * @type String
       
   516         * @default Y.Uploader.Queue.CONTINUE
       
   517         */
       
   518         errorAction: {
       
   519             value: "continue",
       
   520                 validator: function (val) {
       
   521                 return (
       
   522                     val === UploaderQueue.CONTINUE ||
       
   523                     val === UploaderQueue.STOP ||
       
   524                     val === UploaderQueue.RESTART_ASAP ||
       
   525                     val === UploaderQueue.RESTART_AFTER
       
   526                 );
       
   527             }
       
   528         },
       
   529 
       
   530         /**
       
   531         * The total number of bytes that has been uploaded.
       
   532         * @attribute bytesUploaded
       
   533         * @type Number
       
   534         */
       
   535         bytesUploaded: {
       
   536             readOnly: true,
       
   537             value: 0
       
   538         },
       
   539 
       
   540         /**
       
   541         * The total number of bytes in the queue.
       
   542         * @attribute bytesTotal
       
   543         * @type Number
       
   544         */
       
   545         bytesTotal: {
       
   546             readOnly: true,
       
   547             value: 0
       
   548         },
       
   549 
       
   550         /**
       
   551         * The queue file list. This file list should only be modified
       
   552         * before the upload has been started; modifying it after starting
       
   553         * the upload has no effect, and `addToQueueTop` or `addToQueueBottom` methods
       
   554         * should be used instead.
       
   555         * @attribute fileList
       
   556         * @type Array
       
   557         */
       
   558         fileList: {
       
   559             value: [],
       
   560             lazyAdd: false,
       
   561             setter: function (val) {
       
   562                 var newValue = val;
       
   563                 Y.Array.each(newValue, function (value) {
       
   564                     this.totalBytes += value.get("size");
       
   565                 }, this);
       
   566 
       
   567                 return val;
       
   568             }
       
   569         },
       
   570 
       
   571         /**
       
   572         * A String specifying what should be the POST field name for the file
       
   573         * content in the upload request.
       
   574         *
       
   575         * @attribute fileFieldName
       
   576         * @type {String}
       
   577         * @default Filedata
       
   578         */
       
   579         fileFieldName: {
       
   580             value: "Filedata"
       
   581         },
       
   582 
       
   583         /**
       
   584         * The URL to POST the file upload requests to.
       
   585         *
       
   586         * @attribute uploadURL
       
   587         * @type {String}
       
   588         * @default ""
       
   589         */
       
   590         uploadURL: {
       
   591             value: ""
       
   592         },
       
   593 
       
   594         /**
       
   595         * Additional HTTP headers that should be included
       
   596         * in the upload request. Due to Flash Player security
       
   597         * restrictions, this attribute is only honored in the
       
   598         * HTML5 Uploader.
       
   599         *
       
   600         * @attribute uploadHeaders
       
   601         * @type {Object}
       
   602         * @default {}
       
   603         */
       
   604         uploadHeaders: {
       
   605             value: {}
       
   606         },
       
   607 
       
   608         /**
       
   609         * A Boolean that specifies whether the file should be
       
   610         * uploaded with the appropriate user credentials for the
       
   611         * domain. Due to Flash Player security restrictions, this
       
   612         * attribute is only honored in the HTML5 Uploader.
       
   613         *
       
   614         * @attribute withCredentials
       
   615         * @type {Boolean}
       
   616         * @default true
       
   617         */
       
   618         withCredentials: {
       
   619             value: true
       
   620         },
       
   621 
       
   622 
       
   623         /**
       
   624         * An object, keyed by `fileId`, containing sets of key-value pairs
       
   625         * that should be passed as POST variables along with each corresponding
       
   626         * file.
       
   627         *
       
   628         * @attribute perFileParameters
       
   629         * @type {Object}
       
   630         * @default {}
       
   631         */
       
   632         perFileParameters: {
       
   633             value: {}
       
   634         },
       
   635 
       
   636         /**
       
   637         * The number of times to try re-uploading a file that failed to upload before
       
   638         * cancelling its upload.
       
   639         *
       
   640         * @attribute retryCount
       
   641         * @type {Number}
       
   642         * @default 3
       
   643         */
       
   644         retryCount: {
       
   645             value: 3
       
   646         }
       
   647 
       
   648     }
       
   649 });
       
   650 
       
   651 
       
   652 Y.namespace('Uploader');
       
   653 Y.Uploader.Queue = UploaderQueue;
       
   654 
       
   655 
       
   656 }, '@VERSION@', {"requires": ["base"]});