|
15 | 15 | * @param {number} [opts.progressCallbacksInterval] |
16 | 16 | * @param {number} [opts.speedSmoothingFactor] |
17 | 17 | * @param {Object|Function} [opts.query] |
18 | | - * @param {Object} [opts.headers] |
| 18 | + * @param {Object|Function} [opts.headers] |
19 | 19 | * @param {bool} [opts.withCredentials] |
20 | 20 | * @param {Function} [opts.preprocess] |
21 | 21 | * @param {string} [opts.method] |
22 | 22 | * @param {bool} [opts.prioritizeFirstAndLastChunk] |
23 | | - * @param {string} [opts.target] |
| 23 | + * @param {string|Function} [opts.target] |
24 | 24 | * @param {number} [opts.maxChunkRetries] |
25 | 25 | * @param {number} [opts.chunkRetryInterval] |
26 | 26 | * @param {Array.<number>} [opts.permanentErrors] |
|
443 | 443 | return uploading; |
444 | 444 | }, |
445 | 445 |
|
| 446 | + /** |
| 447 | + * should upload next chunk |
| 448 | + * @function |
| 449 | + * @returns {boolean|number} |
| 450 | + */ |
| 451 | + _shouldUploadNext: function () { |
| 452 | + var num = 0; |
| 453 | + var should = true; |
| 454 | + var simultaneousUploads = this.opts.simultaneousUploads; |
| 455 | + each(this.files, function (file) { |
| 456 | + each(file.chunks, function(chunk) { |
| 457 | + if (chunk.status() === 'uploading') { |
| 458 | + num++; |
| 459 | + if (num >= simultaneousUploads) { |
| 460 | + should = false; |
| 461 | + return false; |
| 462 | + } |
| 463 | + } |
| 464 | + }); |
| 465 | + }); |
| 466 | + // if should is true then return uploading chunks's length |
| 467 | + return should && num; |
| 468 | + }, |
| 469 | + |
446 | 470 | /** |
447 | 471 | * Start or resume uploading. |
448 | 472 | * @function |
449 | 473 | */ |
450 | 474 | upload: function () { |
451 | 475 | // Make sure we don't start too many uploads at once |
452 | | - if (this.isUploading()) { |
| 476 | + var ret = this._shouldUploadNext(); |
| 477 | + if (ret === false) { |
453 | 478 | return; |
454 | 479 | } |
455 | 480 | // Kick off the queue |
456 | 481 | this.fire('uploadStart'); |
457 | 482 | var started = false; |
458 | | - for (var num = 1; num <= this.opts.simultaneousUploads; num++) { |
| 483 | + for (var num = 1; num <= this.opts.simultaneousUploads - ret; num++) { |
459 | 484 | started = this.uploadNextChunk(true) || started; |
460 | 485 | } |
461 | 486 | if (!started) { |
|
1174 | 1199 | * @param params |
1175 | 1200 | * @returns {string} |
1176 | 1201 | */ |
1177 | | - getTarget: function(params){ |
1178 | | - var target = this.flowObj.opts.target; |
| 1202 | + getTarget: function(target, params){ |
1179 | 1203 | if(target.indexOf('?') < 0) { |
1180 | 1204 | target += '?'; |
1181 | 1205 | } else { |
|
1194 | 1218 | this.xhr = new XMLHttpRequest(); |
1195 | 1219 | this.xhr.addEventListener("load", this.testHandler, false); |
1196 | 1220 | this.xhr.addEventListener("error", this.testHandler, false); |
1197 | | - var data = this.prepareXhrRequest('GET'); |
| 1221 | + var data = this.prepareXhrRequest('GET', true); |
1198 | 1222 | this.xhr.send(data); |
1199 | 1223 | }, |
1200 | 1224 |
|
|
1246 | 1270 | this.xhr.addEventListener("load", this.doneHandler, false); |
1247 | 1271 | this.xhr.addEventListener("error", this.doneHandler, false); |
1248 | 1272 |
|
1249 | | - var data = this.prepareXhrRequest('POST', this.flowObj.opts.method, bytes); |
1250 | | - |
| 1273 | + var data = this.prepareXhrRequest('POST', false, this.flowObj.opts.method, bytes); |
1251 | 1274 | this.xhr.send(data); |
1252 | 1275 | }, |
1253 | 1276 |
|
|
1342 | 1365 | /** |
1343 | 1366 | * Prepare Xhr request. Set query, headers and data |
1344 | 1367 | * @param {string} method GET or POST |
| 1368 | + * @param {bool} isTest is this a test request |
1345 | 1369 | * @param {string} [paramsMethod] octet or form |
1346 | 1370 | * @param {Blob} [blob] to send |
1347 | 1371 | * @returns {FormData|Blob|Null} data to send |
1348 | 1372 | */ |
1349 | | - prepareXhrRequest: function(method, paramsMethod, blob) { |
| 1373 | + prepareXhrRequest: function(method, isTest, paramsMethod, blob) { |
1350 | 1374 | // Add data from the query options |
1351 | | - var query = this.flowObj.opts.query; |
1352 | | - if (typeof query === "function") { |
1353 | | - query = query(this.fileObj, this); |
1354 | | - } |
| 1375 | + var query = evalOpts(this.flowObj.opts.query, this.fileObj, this, isTest); |
1355 | 1376 | query = extend(this.getParams(), query); |
1356 | 1377 |
|
1357 | | - var target = this.flowObj.opts.target; |
| 1378 | + var target = evalOpts(this.flowObj.opts.target, this.fileObj, this, isTest); |
1358 | 1379 | var data = null; |
1359 | 1380 | if (method === 'GET' || paramsMethod === 'octet') { |
1360 | 1381 | // Add data from the query options |
1361 | 1382 | var params = []; |
1362 | 1383 | each(query, function (v, k) { |
1363 | 1384 | params.push([encodeURIComponent(k), encodeURIComponent(v)].join('=')); |
1364 | 1385 | }); |
1365 | | - target = this.getTarget(params); |
| 1386 | + target = this.getTarget(target, params); |
1366 | 1387 | data = blob || null; |
1367 | 1388 | } else { |
1368 | 1389 | // Add data from the query options |
|
1377 | 1398 | this.xhr.withCredentials = this.flowObj.opts.withCredentials; |
1378 | 1399 |
|
1379 | 1400 | // Add data from header options |
1380 | | - each(this.flowObj.opts.headers, function (v, k) { |
| 1401 | + each(evalOpts(this.flowObj.opts.headers, this.fileObj, this, isTest), function (v, k) { |
1381 | 1402 | this.xhr.setRequestHeader(k, v); |
1382 | 1403 | }, this); |
1383 | 1404 |
|
|
1397 | 1418 | } |
1398 | 1419 | } |
1399 | 1420 |
|
| 1421 | + /** |
| 1422 | + * If option is a function, evaluate it with given params |
| 1423 | + * @param {*} data |
| 1424 | + * @param {...} args arguments of a callback |
| 1425 | + * @returns {*} |
| 1426 | + */ |
| 1427 | + function evalOpts(data, args) { |
| 1428 | + if (typeof data === "function") { |
| 1429 | + // `arguments` is an object, not array, in FF, so: |
| 1430 | + args = Array.prototype.slice.call(arguments); |
| 1431 | + data = data.apply(null, args.slice(1)); |
| 1432 | + } |
| 1433 | + return data; |
| 1434 | + } |
| 1435 | + Flow.evalOpts = evalOpts; |
| 1436 | + |
1400 | 1437 | /** |
1401 | 1438 | * Execute function asynchronously |
1402 | 1439 | * @param fn |
|
1471 | 1508 | * Library version |
1472 | 1509 | * @type {string} |
1473 | 1510 | */ |
1474 | | - Flow.version = '2.5.0'; |
| 1511 | + Flow.version = '2.6.0'; |
1475 | 1512 |
|
1476 | 1513 | if ( typeof module === "object" && module && typeof module.exports === "object" ) { |
1477 | 1514 | // Expose Flow as module.exports in loaders that implement the Node |
|
0 commit comments