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-queue', function (Y, NAME) {
11
* The class manages a queue of files that should be uploaded to the server.
12
* It initializes the required number of uploads, tracks them as they progress,
13
* and automatically advances to the next upload when a preceding one has completed.
14
* @module uploader-queue
20
* This class manages a queue of files to be uploaded to the server.
21
* @class Uploader.Queue
25
var UploaderQueue = function() {
26
this.queuedFiles = [];
27
this.uploadRetries = {};
28
this.numberOfUploads = 0;
29
this.currentUploadedByteValues = {};
30
this.currentFiles = {};
31
this.totalBytesUploaded = 0;
34
UploaderQueue.superclass.constructor.apply(this, arguments);
38
Y.extend(UploaderQueue, Y.Base, {
41
* Stored value of the current queue state
42
* @property _currentState
45
* @default UploaderQueue.STOPPED
47
_currentState: UploaderQueue.STOPPED,
50
* Construction logic executed during UploaderQueue instantiation.
55
initializer : function () {},
58
* Handles and retransmits upload start event.
60
* @method _uploadStartHandler
61
* @param event The event dispatched during the upload process.
64
_uploadStartHandler : function (event) {
65
var updatedEvent = event;
66
updatedEvent.file = event.target;
67
updatedEvent.originEvent = event;
69
this.fire("uploadstart", updatedEvent);
73
* Handles and retransmits upload error event.
75
* @method _uploadErrorHandler
76
* @param event The event dispatched during the upload process.
79
_uploadErrorHandler : function (event) {
80
var errorAction = this.get("errorAction"),
85
updatedEvent.file = event.target;
86
updatedEvent.originEvent = event;
88
this.numberOfUploads-=1;
89
delete this.currentFiles[event.target.get("id")];
90
this._detachFileEvents(event.target);
92
event.target.cancelUpload();
94
if (errorAction === UploaderQueue.STOP) {
98
else if (errorAction === UploaderQueue.RESTART_ASAP) {
99
fileid = event.target.get("id");
100
retries = this.uploadRetries[fileid] || 0;
102
if (retries < this.get("retryCount")) {
103
this.uploadRetries[fileid] = retries + 1;
104
this.addToQueueTop(event.target);
106
this._startNextFile();
108
else if (errorAction === UploaderQueue.RESTART_AFTER) {
109
fileid = event.target.get("id");
110
retries = this.uploadRetries[fileid] || 0;
112
if (retries < this.get("retryCount")) {
113
this.uploadRetries[fileid] = retries + 1;
114
this.addToQueueBottom(event.target);
116
this._startNextFile();
119
this.fire("uploaderror", updatedEvent);
123
* Launches the upload of the next file in the queue.
125
* @method _startNextFile
128
_startNextFile : function () {
129
if (this.queuedFiles.length > 0) {
130
var currentFile = this.queuedFiles.shift(),
131
fileId = currentFile.get("id"),
132
parameters = this.get("perFileParameters"),
133
fileParameters = parameters.hasOwnProperty(fileId) ? parameters[fileId] : parameters;
135
this.currentUploadedByteValues[fileId] = 0;
137
currentFile.on("uploadstart", this._uploadStartHandler, this);
138
currentFile.on("uploadprogress", this._uploadProgressHandler, this);
139
currentFile.on("uploadcomplete", this._uploadCompleteHandler, this);
140
currentFile.on("uploaderror", this._uploadErrorHandler, this);
141
currentFile.on("uploadcancel", this._uploadCancelHandler, this);
143
currentFile.set("xhrHeaders", this.get("uploadHeaders"));
144
currentFile.set("xhrWithCredentials", this.get("withCredentials"));
146
currentFile.startUpload(this.get("uploadURL"), fileParameters, this.get("fileFieldName"));
148
this._registerUpload(currentFile);
153
* Register a new upload process.
155
* @method _registerUpload
158
_registerUpload : function (file) {
159
this.numberOfUploads += 1;
160
this.currentFiles[file.get("id")] = file;
164
* Unregisters a new upload process.
166
* @method _unregisterUpload
169
_unregisterUpload : function (file) {
170
if (this.numberOfUploads > 0) {
171
this.numberOfUploads -= 1;
174
delete this.currentFiles[file.get("id")];
175
delete this.uploadRetries[file.get("id")];
177
this._detachFileEvents(file);
180
_detachFileEvents : function (file) {
181
file.detach("uploadstart", this._uploadStartHandler);
182
file.detach("uploadprogress", this._uploadProgressHandler);
183
file.detach("uploadcomplete", this._uploadCompleteHandler);
184
file.detach("uploaderror", this._uploadErrorHandler);
185
file.detach("uploadcancel", this._uploadCancelHandler);
189
* Handles and retransmits upload complete event.
191
* @method _uploadCompleteHandler
192
* @param event The event dispatched during the upload process.
195
_uploadCompleteHandler : function (event) {
197
this._unregisterUpload(event.target);
199
this.totalBytesUploaded += event.target.get("size");
200
delete this.currentUploadedByteValues[event.target.get("id")];
203
if (this.queuedFiles.length > 0 && this._currentState === UploaderQueue.UPLOADING) {
204
this._startNextFile();
207
var updatedEvent = event,
208
uploadedTotal = this.totalBytesUploaded,
209
percentLoaded = Math.min(100, Math.round(10000*uploadedTotal/this.totalBytes) / 100);
211
updatedEvent.file = event.target;
212
updatedEvent.originEvent = event;
214
Y.each(this.currentUploadedByteValues, function (value) {
215
uploadedTotal += value;
218
this.fire("totaluploadprogress", {
219
bytesLoaded: uploadedTotal,
220
bytesTotal: this.totalBytes,
221
percentLoaded: percentLoaded
224
this.fire("uploadcomplete", updatedEvent);
226
if (this.queuedFiles.length === 0 && this.numberOfUploads <= 0) {
227
this.fire("alluploadscomplete");
228
this._currentState = UploaderQueue.STOPPED;
233
* Handles and retransmits upload cancel event.
235
* @method _uploadCancelHandler
236
* @param event The event dispatched during the upload process.
239
_uploadCancelHandler : function (event) {
241
var updatedEvent = event;
242
updatedEvent.originEvent = event;
243
updatedEvent.file = event.target;
245
this.fire("uploadcancel", updatedEvent);
251
* Handles and retransmits upload progress event.
253
* @method _uploadProgressHandler
254
* @param event The event dispatched during the upload process.
257
_uploadProgressHandler : function (event) {
259
this.currentUploadedByteValues[event.target.get("id")] = event.bytesLoaded;
261
var updatedEvent = event,
262
uploadedTotal = this.totalBytesUploaded,
263
percentLoaded = Math.min(100, Math.round(10000*uploadedTotal/this.totalBytes) / 100);
265
updatedEvent.originEvent = event;
266
updatedEvent.file = event.target;
268
this.fire("uploadprogress", updatedEvent);
270
Y.each(this.currentUploadedByteValues, function (value) {
271
uploadedTotal += value;
274
this.fire("totaluploadprogress", {
275
bytesLoaded: uploadedTotal,
276
bytesTotal: this.totalBytes,
277
percentLoaded: percentLoaded
282
* Starts uploading the queued up file list.
284
* @method startUpload
286
startUpload: function() {
287
this.queuedFiles = this.get("fileList").slice(0);
288
this.numberOfUploads = 0;
289
this.currentUploadedByteValues = {};
290
this.currentFiles = {};
291
this.totalBytesUploaded = 0;
293
this._currentState = UploaderQueue.UPLOADING;
295
while (this.numberOfUploads < this.get("simUploads") && this.queuedFiles.length > 0) {
296
this._startNextFile();
301
* Pauses the upload process. The ongoing file uploads
302
* will complete after this method is called, but no
303
* new ones will be launched.
305
* @method pauseUpload
307
pauseUpload: function () {
308
this._currentState = UploaderQueue.STOPPED;
312
* Restarts a paused upload process.
314
* @method restartUpload
316
restartUpload: function () {
317
this._currentState = UploaderQueue.UPLOADING;
318
while (this.numberOfUploads < this.get("simUploads")) {
319
this._startNextFile();
324
* If a particular file is stuck in an ongoing upload without
325
* any progress events, this method allows to force its reupload
326
* by cancelling its upload and immediately relaunching it.
328
* @method forceReupload
329
* @param file {Y.File} The file to force reupload on.
331
forceReupload : function (file) {
332
var id = file.get("id");
333
if (this.currentFiles.hasOwnProperty(id)) {
335
this._unregisterUpload(file);
336
this.addToQueueTop(file);
337
this._startNextFile();
342
* Add a new file to the top of the queue (the upload will be
343
* launched as soon as the current number of uploading files
344
* drops below the maximum permissible value).
346
* @method addToQueueTop
347
* @param file {Y.File} The file to add to the top of the queue.
349
addToQueueTop: function (file) {
350
this.queuedFiles.unshift(file);
354
* Add a new file to the bottom of the queue (the upload will be
355
* launched after all the other queued files are uploaded.)
357
* @method addToQueueBottom
358
* @param file {Y.File} The file to add to the bottom of the queue.
360
addToQueueBottom: function (file) {
361
this.queuedFiles.push(file);
365
* Cancels a specific file's upload. If no argument is passed,
366
* all ongoing uploads are cancelled and the upload process is
369
* @method cancelUpload
370
* @param file {Y.File} An optional parameter - the file whose upload
371
* should be cancelled.
373
cancelUpload: function (file) {
381
if (this.currentFiles[id]) {
382
this.currentFiles[id].cancelUpload();
383
this._unregisterUpload(this.currentFiles[id]);
384
if (this._currentState === UploaderQueue.UPLOADING) {
385
this._startNextFile();
389
for (i = 0, len = this.queuedFiles.length; i < len; i++) {
390
if (this.queuedFiles[i].get("id") === id) {
391
this.queuedFiles.splice(i, 1);
398
for (fid in this.currentFiles) {
399
this.currentFiles[fid].cancelUpload();
400
this._unregisterUpload(this.currentFiles[fid]);
403
this.currentUploadedByteValues = {};
404
this.currentFiles = {};
405
this.totalBytesUploaded = 0;
406
this.fire("alluploadscancelled");
407
this._currentState = UploaderQueue.STOPPED;
412
* Static constant for the value of the `errorAction` attribute:
413
* prescribes the queue to continue uploading files in case of
420
CONTINUE: "continue",
423
* Static constant for the value of the `errorAction` attribute:
424
* prescribes the queue to stop uploading files in case of
434
* Static constant for the value of the `errorAction` attribute:
435
* prescribes the queue to restart a file upload immediately in case of
437
* @property RESTART_ASAP
442
RESTART_ASAP: "restartasap",
445
* Static constant for the value of the `errorAction` attribute:
446
* prescribes the queue to restart an errored out file upload after
447
* other files have finished uploading.
448
* @property RESTART_AFTER
453
RESTART_AFTER: "restartafter",
456
* Static constant for the value of the `_currentState` property:
457
* implies that the queue is currently not uploading files.
466
* Static constant for the value of the `_currentState` property:
467
* implies that the queue is currently uploading files.
468
* @property UPLOADING
473
UPLOADING: "uploading",
476
* The identity of the class.
480
* @default 'uploaderqueue'
485
NAME: 'uploaderqueue',
488
* Static property used to define the default attribute configuration of
499
* Maximum number of simultaneous uploads; must be in the
500
* range between 1 and 5. The value of `2` is default. It
501
* is recommended that this value does not exceed 3.
502
* @attribute simUploads
508
validator: function (val) {
509
return (val >= 1 && val <= 5);
514
* The action to take in case of error. The valid values for this attribute are:
515
* `Y.Uploader.Queue.CONTINUE` (the upload process should continue on other files,
516
* ignoring the error), `Y.Uploader.Queue.STOP` (the upload process
517
* should stop completely), `Y.Uploader.Queue.RESTART_ASAP` (the upload
518
* should restart immediately on the errored out file and continue as planned), or
519
* Y.Uploader.Queue.RESTART_AFTER (the upload of the errored out file should restart
520
* after all other files have uploaded)
521
* @attribute errorAction
523
* @default Y.Uploader.Queue.CONTINUE
527
validator: function (val) {
529
val === UploaderQueue.CONTINUE ||
530
val === UploaderQueue.STOP ||
531
val === UploaderQueue.RESTART_ASAP ||
532
val === UploaderQueue.RESTART_AFTER
538
* The total number of bytes that has been uploaded.
539
* @attribute bytesUploaded
548
* The total number of bytes in the queue.
549
* @attribute bytesTotal
558
* The queue file list. This file list should only be modified
559
* before the upload has been started; modifying it after starting
560
* the upload has no effect, and `addToQueueTop` or `addToQueueBottom` methods
561
* should be used instead.
562
* @attribute fileList
568
setter: function (val) {
570
Y.Array.each(newValue, function (value) {
571
this.totalBytes += value.get("size");
579
* A String specifying what should be the POST field name for the file
580
* content in the upload request.
582
* @attribute fileFieldName
591
* The URL to POST the file upload requests to.
593
* @attribute uploadURL
602
* Additional HTTP headers that should be included
603
* in the upload request. Due to Flash Player security
604
* restrictions, this attribute is only honored in the
607
* @attribute uploadHeaders
616
* A Boolean that specifies whether the file should be
617
* uploaded with the appropriate user credentials for the
618
* domain. Due to Flash Player security restrictions, this
619
* attribute is only honored in the HTML5 Uploader.
621
* @attribute withCredentials
631
* An object, keyed by `fileId`, containing sets of key-value pairs
632
* that should be passed as POST variables along with each corresponding
635
* @attribute perFileParameters
644
* The number of times to try re-uploading a file that failed to upload before
645
* cancelling its upload.
647
* @attribute retryCount
659
Y.namespace('Uploader');
660
Y.Uploader.Queue = UploaderQueue;
663
}, '3.13.0', {"requires": ["base"]});