uploadqueue.js revision 4751573f6062da85435e345520a7525e91a897ea
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney /**
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * The class manages a queue of files that should be uploaded to the server.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * It initializes the required number of uploads, tracks them as they progress,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * and automatically advances to the next upload when a preceding one has completed.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @module uploadqueue
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney */
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney /**
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * The class manages a queue of files to be uploaded to the server.
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @class UploadQueue
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @extends Base
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @constructor
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney */
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var Lang = Y.Lang,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Bind = Y.bind,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Win = Y.config.win,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney currentUploads,
c329316f92fdab3b92802fb2182e5b5f543d295eDav Glass lastUploadPointer,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney fileListLength,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney uploadsLeftCounter,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney totalBytesUploaded,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney totalBytes;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var UploadQueue = function(o) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney currentUploads = {};
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney lastUploadPointer = 0;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney fileListLength = 0;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney uploadsLeftCounter = 0;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney totalBytesUploaded = 0;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney totalBytes = 0;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney UploadQueue.superclass.constructor.apply(this, arguments);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney };
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Y.extend(UploadQueue, Y.Base, {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney initializer : function (cfg) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney _uploadCompleteHandler : function (event) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney uploadsLeftCounter -= 1;
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney
0204a57902813e8b151b1e98020d8e89997b283eMatt Sweeney totalBytesUploaded += event.target.get("size");
0204a57902813e8b151b1e98020d8e89997b283eMatt Sweeney delete currentUploads[event.target.get("id")];
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney if (lastUploadPointer < fileListLength) {
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney var currentFile = this.get("fileList")[lastUploadPointer],
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney parameters = this.get("perFileParameters"),
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney fileParameters = Lang.isArray(parameters) ? parameters[lastUploadPointer] : parameters;
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney currentFile.on("uploadprogress", this._uploadProgressHandler, this);
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney currentFile.on("uploadcomplete", this._uploadCompleteHandler, this);
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney currentFile.startUpload(this.get("uploadURL"), fileParameters);
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney currentUploads[currentFile.get("id")] = 0;
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney lastUploadPointer += 1;
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney }
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney var updatedEvent = event;
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney updatedEvent.file = event.target;
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney updatedEvent.originEvent = event;
6e32c30fa308d7f01a91d97f9ec19d0a57901ebeMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney this.fire("uploadcomplete", updatedEvent);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney if (uploadsLeftCounter == 0) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney this.fire("alluploadscomplete");
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney _uploadProgressHandler : function (event) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney currentUploads[event.target.get("id")] = event.bytesLoaded;
80d53e62b2ae5fa5ab6ae4fbcfcbfd8ef5764dd7Matt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var updatedEvent = event;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney updatedEvent.originEvent = event;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney updatedEvent.file = event.target;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney this.fire("uploadprogress", updatedEvent);
80d53e62b2ae5fa5ab6ae4fbcfcbfd8ef5764dd7Matt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var uploadedTotal = totalBytesUploaded;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Y.each(currentUploads, function (value) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney uploadedTotal += value;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney });
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var percentLoaded = Math.min(100, Math.round(10000*uploadedTotal/totalBytes) / 100);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney this.fire("totaluploadprogress", {bytesLoaded: uploadedTotal,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney bytesTotal: totalBytes,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney percentLoaded: percentLoaded});
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
80d53e62b2ae5fa5ab6ae4fbcfcbfd8ef5764dd7Matt Sweeney startUpload: function() {
deb3172da8a688abb44a22d5b084c4dd0437df89Matt Sweeney
deb3172da8a688abb44a22d5b084c4dd0437df89Matt Sweeney while (lastUploadPointer < this.get("simUploads") && lastUploadPointer < fileListLength) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
deb3172da8a688abb44a22d5b084c4dd0437df89Matt Sweeney var currentFile = this.get("fileList")[lastUploadPointer],
deb3172da8a688abb44a22d5b084c4dd0437df89Matt Sweeney fileId = currentFile.get("id"),
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney parameters = this.get("perFileParameters"),
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney fileParameters = Lang.isArray(parameters) ? parameters[lastUploadPointer] : parameters;
deb3172da8a688abb44a22d5b084c4dd0437df89Matt Sweeney
deb3172da8a688abb44a22d5b084c4dd0437df89Matt Sweeney currentUploads[fileId] = 0;
deb3172da8a688abb44a22d5b084c4dd0437df89Matt Sweeney
deb3172da8a688abb44a22d5b084c4dd0437df89Matt Sweeney currentFile.on("uploadprogress", this._uploadProgressHandler, this);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney currentFile.on("uploadcomplete", this._uploadCompleteHandler, this);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney currentFile.startUpload(this.get("uploadURL"), fileParameters);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney lastUploadPointer+=1;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney pauseUpload: function () {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney restartUpload: function () {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney cancelUpload: function () {
80d53e62b2ae5fa5ab6ae4fbcfcbfd8ef5764dd7Matt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }, {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney NAME: 'uploadqueue',
80d53e62b2ae5fa5ab6ae4fbcfcbfd8ef5764dd7Matt Sweeney
80d53e62b2ae5fa5ab6ae4fbcfcbfd8ef5764dd7Matt Sweeney ATTRS: {
80d53e62b2ae5fa5ab6ae4fbcfcbfd8ef5764dd7Matt Sweeney
80d53e62b2ae5fa5ab6ae4fbcfcbfd8ef5764dd7Matt Sweeney /**
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @property simUploads
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @type Number
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney * @description Maximum number of simultaneous uploads
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney */
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney simUploads: {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney value: 2,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney validator: function (val, name) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return (val >= 2 && val <= 5);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney errorAction: {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney value: UploadQueue.CONTINUE,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney validator: function (val, name) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return (val === UploadQueue.CONTINUE || val === UploadQueue.STOP || val === UploadQueue.RESTART);
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney bytesUploaded: {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney readOnly: true,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney value: 0
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney bytesTotal: {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney readOnly: true,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney value: 0
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney fileList: {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney value: [],
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney lazyAdd: false,
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney setter: function (val) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney var newValue = val;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Y.each(newValue, function (value) {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney totalBytes += value.get("size");
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney });
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney fileListLength = uploadsLeftCounter = newValue.length;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney return val;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney uploadURL: {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney value: ""
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney perFileParameters: {
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney value: []
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney }
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney },
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney CONTINUE: "continue",
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney STOP: "stop",
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney RESTART: "restart"
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney });
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Y.namespace('Uploader');
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney Y.Uploader.UploadQueue = UploadQueue;
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney
7360d0583edbc1cd77cd7e6d85ee9bcc26e3211dMatt Sweeney