flowjs/flow.js

View on GitHub
samples/java/web/resumable.js

Summary

Maintainability
F
4 days
Test Coverage
// Generated by CoffeeScript 1.6.1
(function() {
  var Resumable, ResumableChunk, ResumableFile,
    __slice = [].slice,
    __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

  window.Resumable = Resumable = (function() {

    function Resumable(opt) {
      this.opt = opt;
      console.log('constructor');
      this.support = (typeof File !== "undefined" && File !== null) && (typeof Blob !== "undefined" && Blob !== null) && (typeof FileList !== "undefined" && FileList !== null) && ((Blob.prototype.webkitSlice != null) || (Blob.prototype.mozSlice != null) || (Blob.prototype.slice != null));
      this.files = [];
      this.defaults = {
        chunkSize: 1 * 1024 * 1024,
        forceChunkSize: false,
        simultaneousUploads: 3,
        fileParameterName: 'file',
        throttleProgressCallbacks: 0.5,
        query: {},
        headers: {},
        preprocess: null,
        method: 'multipart',
        prioritizeFirstAndLastChunk: false,
        target: '/',
        testChunks: true,
        generateUniqueIdentifier: null,
        maxChunkRetries: void 0,
        chunkRetryInterval: void 0,
        permanentErrors: [415, 500, 501],
        maxFiles: void 0,
        maxFilesErrorCallback: function(files, errorCount) {
          var maxFiles, _ref;
          maxFiles = this.getOpt('maxFiles');
          return alert('Please upload ' + maxFiles + ' file' + ((_ref = maxFiles === 1) != null ? _ref : {
            '': 's'
          }) + ' at a time.');
        },
        minFileSize: void 0,
        minFileSizeErrorCallback: function(file, errorCount) {
          return alert(file.fileName(+' is too small, please upload files larger than ' + this.formatSize(this.getOpt('minFileSize')) + '.'));
        },
        maxFileSize: void 0,
        maxFileSizeErrorCallback: function(file, errorCount) {
          return alert(file.fileName(+' is too large, please upload files less than ' + this.formatSize(this.getOpt('maxFileSize')) + '.'));
        }
      };
      if (this.opt == null) {
        this.opt = {};
      }
      this.events = [];
    }

    Resumable.prototype.getOpt = function(o) {
      var item, opts, _i, _len;
      if (o instanceof Array) {
        opts = {};
        for (_i = 0, _len = o.length; _i < _len; _i++) {
          item = o[_i];
          opts[item] = this.getOpt(item);
        }
        return opts;
      } else {
        if (this.opt[o] != null) {
          return this.opt[o];
        } else {
          return this.defaults[o];
        }
      }
    };

    Resumable.prototype.formatSize = function(size) {
      if (size < 1024) {
        return size + ' bytes';
      } else if (size < 1024 * 1024) {
        return (size / 1024.0).toFixed(0) + ' KB';
      } else if (size < 1024 * 1024 * 1024) {
        return (size / 1024.0 / 1024.0).toFixed(1) + ' MB';
      } else {
        return (size / 1024.0 / 1024.0 / 1024.0).toFixed(1) + ' GB';
      }
    };

    Resumable.prototype.stopEvent = function(e) {
      console.log('stopEvent');
      e.stopPropagation();
      return e.preventDefault();
    };

    Resumable.prototype.generateUniqueIdentifier = function(file) {
      var custom, relativePath, size;
      console.log('generateUniqueIdentifier');
      custom = this.getOpt('generateUniqueIdentifier');
      if (typeof custom === 'function') {
        return custom(file);
      } else {
        relativePath = file.webkitRelativePath || file.fileName || file.name;
        size = file.size;
        return size + '-' + relativePath.replace(/[^0-9a-zA-Z_-]/img, '');
      }
    };

    Resumable.prototype.on = function(event, callback) {
      console.log("on: " + event);
      return this.events.push({
        event: event,
        callback: callback
      });
    };

    Resumable.prototype.fire = function() {
      var args, e, event, _i, _len, _ref;
      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
      console.log("fire: " + args[0]);
      event = args[0].toLowerCase();
      _ref = this.events;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        e = _ref[_i];
        if (e.event.toLowerCase() === event) {
          e.callback.apply(this, args.slice(1));
        }
        if (e.event.toLowerCase() === 'catchall') {
          e.callback.apply(null, args);
        }
      }
      if (event === 'fireerror') {
        this.fire('error', args[2], args[1]);
      }
      if (event === 'fileprogress') {
        return this.fire('progress');
      }
    };

    Resumable.prototype.onDrop = function(event) {
      console.log("onDrop");
      this.stopEvent(event);
      return this.appendFilesFromFileList(event.dataTransfer.files, event);
    };

    Resumable.prototype.onDragOver = function(event) {
      console.log("onDragOver");
      return event.preventDefault();
    };

    Resumable.prototype.appendFilesFromFileList = function(fileList, event) {
      var errorCount, file, files, maxFileSize, maxFileSizeErrorCallback, maxFiles, maxFilesErrorCallback, minFileSize, minFileSizeErrorCallback, resumableFile, _i, _len, _ref;
      console.log("appendFilesFromFileList");
      errorCount = 0;
      _ref = this.getOpt(['maxFiles', 'minFileSize', 'maxFileSize', 'maxFilesErrorCallback', 'minFileSizeErrorCallback', 'maxFileSizeErrorCallback']), maxFiles = _ref[0], minFileSize = _ref[1], maxFileSize = _ref[2], maxFilesErrorCallback = _ref[3], minFileSizeErrorCallback = _ref[4], maxFileSizeErrorCallback = _ref[5];
      if ((maxFiles != null) && maxFiles < (fileList.length + this.files.length)) {
        maxFilesErrorCallback(fileList, errorCount++);
        return false;
      }
      files = [];
      for (_i = 0, _len = fileList.length; _i < _len; _i++) {
        file = fileList[_i];
        file.name = file.fileName = file.name || file.fileName;
        if ((minFileSize != null) && file.size < minFileSize) {
          minFileSizeErrorCallback(file, errorCount++);
          return false;
        }
        if ((maxFileSize != null) && file.size > maxFileSize) {
          maxFilesErrorCallback(file, errorCount++);
          return false;
        }
        if (file.size > 0 && !this.getFromUniqueIdentifier(this.generateUniqueIdentifier(file))) {
          resumableFile = new ResumableFile(this, file);
          this.files.push(resumableFile);
          files.push(resumableFile);
          this.fire('fileAdded', resumableFile, event);
        }
      }
      return this.fire('fileAdded', files);
    };

    Resumable.prototype.uploadNextChunk = function() {
      var chunk, file, found, outstanding, status, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4;
      console.log("uploadNextChunk");
      found = false;
      if (this.getOpt('prioritizeFirstAndLastChunk')) {
        _ref = this.files;
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          file = _ref[_i];
          if (file.chunks.length && file.chunks[0].status() === 'pending' && file.chunks[0].preprocessState === 0) {
            file.chunks[0].send();
            found = true;
            break;
          }
          if (file.chunks.length > 1 && file.chunks[file.chunks.length - 1].status() === 'pending' && file.chunks[file.chunks.length - 1].preprocessState === 0) {
            file.chunks[file.chunks.length - 1].send();
            found = true;
            break;
          }
        }
        if (found) {
          return true;
        }
      }
      _ref1 = this.files;
      for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
        file = _ref1[_j];
        _ref2 = file.chunks;
        for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
          chunk = _ref2[_k];
          if (chunk.status() === 'pending' && chunk.preprocessState === 0) {
            chunk.send();
            found = true;
            break;
          }
        }
        if (found) {
          break;
        }
      }
      if (found) {
        return true;
      }
      _ref3 = this.files;
      for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
        file = _ref3[_l];
        outstanding = false;
        _ref4 = file.chunks;
        for (_m = 0, _len4 = _ref4.length; _m < _len4; _m++) {
          chunk = _ref4[_m];
          status = chunk.status();
          if (status === 'pending' || status === 'uploading' || chunk.preprocessState === 1) {
            outstanding = true;
            break;
          }
        }
        if (outstanding) {
          break;
        }
      }
      if (!outstanding) {
        this.fire('complete');
      }
      return false;
    };

    Resumable.prototype.assignBrowse = function(domNodes, isDirectory) {
      var changeHandler, dn, input, maxFiles, _i, _len,
        _this = this;
      console.log("assignBrowse");
      if (domNodes.length == null) {
        domNodes = [domNodes];
      }
      for (_i = 0, _len = domNodes.length; _i < _len; _i++) {
        dn = domNodes[_i];
        if (dn.tagName === 'INPUT' && dn.type === 'file') {
          input = dn;
        } else {
          input = document.createElement('input');
          input.setAttribute('type', 'file');
          dn.style.display = 'inline-block';
          dn.style.position = 'relative';
          input.style.position = 'absolute';
          input.style.top = input.style.left = input.style.bottom = input.style.right = 0;
          input.style.opacity = 0;
          input.style.cursor = 'pointer';
          dn.appendChild(input);
        }
      }
      maxFiles = this.getOpt('maxFiles');
      if ((maxFiles != null) || maxFiles !== 1) {
        input.setAttribute('multiple', 'multiple');
      } else {
        input.removeAttribute('multiple');
      }
      if (isDirectory) {
        input.setAttribute('webkitdirectory', 'webkitdirectory');
      } else {
        input.removeAttribute('webkitdirectory');
      }
      changeHandler = function(e) {
        _this.appendFilesFromFileList(e.target.files);
        return e.target.value = '';
      };
      return input.addEventListener('change', changeHandler, false);
    };

    Resumable.prototype.assignDrop = function(domNodes) {
      var dn, _i, _len, _results;
      console.log("assignDrop");
      if (domNodes.length == null) {
        domNodes = [domNodes];
      }
      _results = [];
      for (_i = 0, _len = domNodes.length; _i < _len; _i++) {
        dn = domNodes[_i];
        dn.addEventListener('dragover', this.onDragOver, false);
        _results.push(dn.addEventListener('drop', this.onDrop, false));
      }
      return _results;
    };

    Resumable.prototype.unAssignDrop = function(domNodes) {
      var dn, _i, _len, _results;
      console.log("unAssignDrop");
      if (domNodes.length == null) {
        domNodes = [domNodes];
      }
      _results = [];
      for (_i = 0, _len = domNodes.length; _i < _len; _i++) {
        dn = domNodes[_i];
        dn.removeEventListener('dragover', this.onDragOver);
        _results.push(dn.removeEventListener('drop', this.onDrop));
      }
      return _results;
    };

    Resumable.prototype.isUploading = function() {
      var chunk, file, uploading, _i, _j, _len, _len1, _ref, _ref1;
      uploading = false;
      _ref = this.files;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        file = _ref[_i];
        _ref1 = file.chunks;
        for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
          chunk = _ref1[_j];
          if (chunk.status() === 'uploading') {
            uploading = true;
            break;
          }
        }
        if (uploading) {
          break;
        }
      }
      return uploading;
    };

    Resumable.prototype.upload = function() {
      var num, _i, _ref, _results;
      console.log("upload");
      if (this.isUploading()) {
        return;
      }
      this.fire('uploadStart');
      _results = [];
      for (num = _i = 0, _ref = this.getOpt('simultaneousUploads'); 0 <= _ref ? _i <= _ref : _i >= _ref; num = 0 <= _ref ? ++_i : --_i) {
        _results.push(this.uploadNextChunk());
      }
      return _results;
    };

    Resumable.prototype.pause = function() {
      var file, _i, _len, _ref;
      console.log("pause");
      _ref = this.files;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        file = _ref[_i];
        file.abort();
      }
      return this.fire('pause');
    };

    Resumable.prototype.cancel = function() {
      var file, _i, _len, _ref;
      console.log("cancel");
      _ref = this.files;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        file = _ref[_i];
        file.cancel();
      }
      return this.fire('cancel');
    };

    Resumable.prototype.progress = function() {
      var file, totalDone, totalSize, _i, _len, _ref;
      console.log("progress");
      totalDone = 0;
      totalSize = 0;
      _ref = this.files;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        file = _ref[_i];
        totalDone += file.progress() * file.size;
        totalSize += file.size;
      }
      return (totalSize > 0 ? totalDone / totalSize : 0);
    };

    Resumable.prototype.addFile = function(file) {
      console.log("addFile");
      return this.appendFilesFromFileList([file]);
    };

    Resumable.prototype.removeFile = function(file) {
      var f, files, _i, _len, _ref;
      console.log("removeFile");
      files = [];
      _ref = this.files;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        f = _ref[_i];
        if (f !== file) {
          files.push(f);
        }
      }
      return this.files = files;
    };

    Resumable.prototype.getFromUniqueIdentifier = function(uniqueIdentifier) {
      var f, _i, _len, _ref;
      console.log("getFromUniqueIdentifier");
      _ref = this.files;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        f = _ref[_i];
        if (f.uniqueIdentifier === uniqueIdentifier) {
          return f;
        }
      }
      return false;
    };

    Resumable.prototype.getSize = function() {
      var file, totalSize, _i, _len, _ref;
      console.log("getSize");
      totalSize = 0;
      _ref = this.files;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        file = _ref[_i];
        totalSize += file.size;
      }
      return totalSize;
    };

    return Resumable;

  })();

  window.ResumableChunk = ResumableChunk = (function() {

    function ResumableChunk(resumableObj, fileObj, offset, callback) {
      this.resumableObj = resumableObj;
      this.fileObj = fileObj;
      this.offset = offset;
      this.callback = callback;
      this.opt = {};
      this.fileObjSize = this.fileObj.size;
      this.lastProgressCallback = new Date;
      this.tested = false;
      this.retries = 0;
      this.preprocessState = 0;
      this.chunkSize = this.getOpt('chunkSize');
      this.loaded = 0;
      this.startByte = this.offset * this.chunkSize;
      this.endByte = Math.min(this.fileObjSize, (this.offset + 1) * this.chunkSize);
      if ((this.fileObjSize - this.endByte < this.chunkSize) && (!this.getOpt('forceChunkSize'))) {
        this.endByte = this.fileObjSize;
      }
      this.xhr = null;
    }

    ResumableChunk.prototype.getOpt = function(o) {
      return this.resumableObj.getOpt(o);
    };

    ResumableChunk.prototype.pushParams = function(params, key, value) {
      return params.push([encodeURIComponent(key), encodeURIComponent(value)].join('='));
    };

    ResumableChunk.prototype.test = function() {
      var customQuery, headers, key, params, testHandler, value,
        _this = this;
      this.xhr = new XMLHttpRequest();
      testHandler = function(e) {
        var status;
        _this.tested = true;
        status = _this.status();
        if (status === 'success') {
          _this.callback(status, _this.message());
          return _this.resumableObj.uploadNextChunk();
        } else {
          return _this.send();
        }
      };
      this.xhr.addEventListener('load', testHandler, false);
      this.xhr.addEventListener('error', testHandler, false);
      params = [];
      customQuery = this.getOpt('query');
      if (typeof customQuery === 'function') {
        customQuery = customQuery(this.fileObj, this);
      }
      if (customQuery != null) {
        for (key in customQuery) {
          value = customQuery[key];
          pushParams(key, value);
        }
      }
      this.pushParams(params, 'resumableChunkNumber', this.offset + 1);
      this.pushParams(params, 'resumableChunkSize', this.chunkSize);
      this.pushParams(params, 'resumableCurrentChunkSize', this.endByte - this.startByte);
      this.pushParams(params, 'resumableTotalSize', this.fileObjSize);
      this.pushParams(params, 'resumableIdentifier', this.fileObj.uniqueIdentifier);
      this.pushParams(params, 'resumableFilename', this.fileObj.fileName);
      this.pushParams(params, 'resumableRelativePath', this.fileObj.relativePath);
      this.xhr.open('GET', this.getOpt('target') + '?' + params.join('&'));
      headers = this.getOpt('headers');
      if (headers == null) {
        headers = {};
      }
      for (key in headers) {
        value = headers[key];
        this.xhr.setRequestHeader(key, value);
      }
      return this.xhr.send(null);
    };

    ResumableChunk.prototype.preprocessFinished = function() {
      this.preprocessState = 2;
      return this.send();
    };

    ResumableChunk.prototype.send = function() {
      var bytes, customQuery, data, doneHandler, func, headers, key, params, preprocess, progressHandler, query, ret, target, value,
        _this = this;
      preprocess = this.getOpt('preprocess');
      if (typeof preprocess === 'function') {
        ret = false;
        switch (this.preprocessState) {
          case 0:
            preprocess(this);
            this.preprocessState = 1;
            ret = true;
            break;
          case 1:
            ret = true;
            break;
          case 2:
            ret = false;
        }
        if (ret) {
          return;
        }
      }
      if (this.getOpt('testChunks') && !this.tested) {
        this.test();
        return;
      }
      this.xhr = new XMLHttpRequest();
      this.loaded = 0;
      progressHandler = function(e) {
        if ((new Date) - _this.lastProgressCallback > _this.getOpt('throttleProgressCallbacks') * 1000) {
          _this.callback('progress');
          _this.lastProgressCallback = new Date;
        }
        return _this.loaded = e.loaded || 0;
      };
      this.xhr.upload.addEventListener('progress', progressHandler, false);
      this.callback('progress');
      doneHandler = function(e) {
        var retryInterval, status;
        status = _this.status();
        if (status === 'success' || status === 'error') {
          _this.callback(status, _this.message());
          return _this.resumableObj.uploadNextChunk();
        } else {
          _this.callback('retry', _this.message());
          _this.abort();
          _this.retries++;
          retryInterval = getOpt('chunkRetryInterval');
          if (retryInterval != null) {
            return setTimeout(_this.send, retryInterval);
          }
        }
      };
      this.xhr.addEventListener('load', doneHandler, false);
      this.xhr.addEventListener('error', doneHandler, false);
      headers = this.getOpt('headers');
      if (headers == null) {
        headers = {};
      }
      for (key in headers) {
        value = headers[key];
        this.xhr.setRequestHeader(key, value);
      }
      if (this.fileObj.file.slice != null) {
        func = 'slice';
      } else if (this.fileObj.file.mozSlice != null) {
        func = 'mozSlice';
      } else if (this.fileObj.file.webkitSlice != null) {
        func = 'webkitSlice';
      } else {
        func = 'slice';
      }
      bytes = this.fileObj.file[func](this.startByte, this.endByte);
      data = null;
      target = this.getOpt('target');
      query = {
        resumableChunkNumber: this.offset + 1,
        resumableChunkSize: this.getOpt('chunkSize'),
        resumableCurrentChunkSize: this.endByte - this.startByte,
        resumableTotalSize: this.fileObjSize,
        resumableIdentifier: this.fileObj.uniqueIdentifier,
        resumableFilename: this.fileObj.fileName,
        resumableRelativePath: this.fileObj.relativePath
      };
      customQuery = this.getOpt('query');
      if (typeof customQuery === 'function') {
        customQuery = customQuery(this.fileObj, this);
      }
      if (customQuery == null) {
        customQuery = {};
      }
      for (key in customQuery) {
        value = customQuery[key];
        pushParams(query, key, value);
      }
      if (this.getOpt('method') === 'octet') {
        data = bytes;
        params = [];
        for (key in query) {
          value = query[key];
          this.pushParams(params, key, value);
        }
        target += '?' + params.join('&');
      } else {
        data = new FormData();
        for (key in query) {
          value = query[key];
          data.append(key, value);
        }
        data.append(this.getOpt('fileParameterName'), bytes);
      }
      this.xhr.open('POST', target);
      return this.xhr.send(data);
    };

    ResumableChunk.prototype.abort = function() {
      if (this.xhr != null) {
        this.xhr.abort();
      }
      return this.xhr = null;
    };

    ResumableChunk.prototype.status = function() {
      var maxChunkRetries, permanentErrors, _ref;
      permanentErrors = this.getOpt('permanentErrors');
      maxChunkRetries = this.getOpt('maxChunkRetries');
      if (permanentErrors == null) {
        permanentErrors = {};
      }
      if (maxChunkRetries == null) {
        maxChunkRetries = 0;
      }
      if (this.xhr == null) {
        return 'pending';
      } else if (this.xhr.readyState < 4) {
        return 'uploading';
      } else if (this.xhr.status === 200) {
        return 'success';
      } else if ((_ref = this.xhr.status, __indexOf.call(permanentErrors, _ref) >= 0) || (this.retries >= maxChunkRetries)) {
        return 'error';
      } else {
        this.abort();
        return 'pending';
      }
    };

    ResumableChunk.prototype.message = function() {
      return (this.xhr != null ? this.xhr.responseText : '');
    };

    ResumableChunk.prototype.progress = function(relative) {
      var factor;
      factor = (relative != null ? (this.endByte - this.startByte) / this.fileObjSize : 1);
      switch (this.status()) {
        case 'success':
        case 'error':
          return 1 * factor;
        case 'pending':
          return 0 * factor;
        default:
          return this.loaded / (this.endByte - this.startByte) * factor;
      }
    };

    return ResumableChunk;

  })();

  window.ResumableFile = ResumableFile = (function() {

    function ResumableFile(resumableObj, file) {
      this.resumableObj = resumableObj;
      this.file = file;
      this.opt = {};
      this._prevProgress = 0;
      this.fileName = this.file.fileName || this.file.name;
      this.size = this.file.size;
      this.relativePath = this.file.webkitRelativePath || this.fileName;
      this.uniqueIdentifier = this.resumableObj.generateUniqueIdentifier(this.file);
      this._error = false;
      this.chunks = [];
      this.bootstrap();
    }

    ResumableFile.prototype.getOpt = function(o) {
      return this.resumableObj.getOpt(o);
    };

    ResumableFile.prototype.chunkEvent = function(event, message) {
      switch (event) {
        case "progress":
          return this.resumableObj.fire('fileProgress', this);
        case "error":
          this.abort();
          this._error = true;
          this.chunks = [];
          return this.resumableObj.fire('fileError', this, message);
        case "success":
          if (!this._error) {
            this.resumableObj.fire('fileProgress', this);
            if (this.progress() === 1) {
              return this.resumableObj.fire('fileSuccess', this, message);
            }
          }
          break;
        case "retry":
          return this.resumableObj.fire('fileRetry', this);
      }
    };

    ResumableFile.prototype.abort = function() {
      var c, _i, _len, _ref;
      _ref = this.chunks;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        c = _ref[_i];
        if (c.status() === 'uploading') {
          c.abort();
        }
      }
      return this.resumableObj.fire('fileProgress', this);
    };

    ResumableFile.prototype.cancel = function() {
      var c, _chunks, _i, _len;
      _chunks = this.chunks;
      this.chunks = [];
      for (_i = 0, _len = _chunks.length; _i < _len; _i++) {
        c = _chunks[_i];
        if (c.status() === 'uploading') {
          c.abort();
          this.resumableObj.uploadNextChunk();
        }
      }
      this.resumableObj.removeFile(this);
      return this.resumableObj.fire('fileProgress', this);
    };

    ResumableFile.prototype.retry = function() {
      this.bootstrap();
      return this.resumableObj.upload();
    };

    ResumableFile.prototype.bootstrap = function() {
      var max, offset, round, _i, _ref, _results;
      this.abort();
      this._error = false;
      this.chunks = [];
      this._prevProgress = 0;
      if (this.getOpt('forceChunkSize') != null) {
        round = Math.ceil;
      } else {
        round = Math.floor;
      }
      offset = 0;
      max = Math.max(round(this.file.size / this.getOpt('chunkSize')), 1);
      _results = [];
      for (offset = _i = 0, _ref = max - 1; 0 <= _ref ? _i <= _ref : _i >= _ref; offset = 0 <= _ref ? ++_i : --_i) {
        _results.push(this.chunks.push(new ResumableChunk(this.resumableObj, this, offset, this.chunkEvent)));
      }
      return _results;
    };

    ResumableFile.prototype.progress = function() {
      var c, error, ret, _i, _len, _ref;
      if (this._error) {
        return 1.;
      }
      ret = 0;
      error = false;
      _ref = this.chunks;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        c = _ref[_i];
        error = c.status() === 'error';
        ret += c.progress(true);
      }
      ret = (error || error > 0.99 ? 1 : ret);
      ret = Math.max(this._prevProgress, ret);
      this._prevProgress = ret;
      return ret;
    };

    return ResumableFile;

  })();

}).call(this);