~andreserl/maas/packaging_precise_rebase

« back to all changes in this revision

Viewing changes to debian/extras/jslibs/yui/uploader-queue/uploader-queue.js

  • Committer: Andres Rodriguez
  • Date: 2013-03-20 18:12:30 UTC
  • mfrom: (145.2.22 precise.sru)
  • Revision ID: andreserl@ubuntu.com-20130320181230-6l5guc0nhlv2z4p7
Re-base againts latest quantal released branch towards SRU

Show diffs side-by-side

added added

removed removed

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