From a1e4006de1781ceb37890d4d0ad8ee77b11d8853 Mon Sep 17 00:00:00 2001 From: Adam Hooper Date: Mon, 2 Feb 2015 15:58:16 -0500 Subject: [PATCH] Use Browserify instead of RequireJS --- .gitignore | 2 - Gruntfile.coffee | 135 - README.md | 17 +- bower.json | 21 - demo/coffee/app.coffee | 27 +- demo/coffee/main.coffee | 20 - demo/coffee/upload-logic.coffee | 82 +- demo/index.html | 2 +- dist/mass-upload.js | 1039 ---- dist/mass-upload.min.js | 1 - dist/mass-upload.no-require.js | 1466 ------ dist/mass-upload.no-require.min.js | 7 - gulpfile.coffee | 72 + gulpfile.js | 2 + js-mass-upload.js | 4180 +++++++++++++++++ js-mass-upload.min.js | 2 + package.json | 41 +- src/MassUpload.coffee | 291 ++ src/MassUpload/FileDeleter.coffee | 53 + src/MassUpload/FileInfo.coffee | 18 + src/MassUpload/FileLister.coffee | 51 + src/MassUpload/FileUploader.coffee | 84 + src/MassUpload/State.coffee | 61 + src/MassUpload/Upload.coffee | 115 + src/MassUpload/UploadCollection.coffee | 221 + src/MassUpload/UploadProgress.coffee | 70 + src/MassUpload/views/AbstractProgress.coffee | 78 + src/MassUpload/views/ListFilesProgress.coffee | 9 + src/MassUpload/views/MassUpload.coffee | 30 + src/MassUpload/views/UploadCollection.coffee | 191 + src/MassUpload/views/UploadProgress.coffee | 10 + src/MassUpload/views/humanReadableSize.coffee | 21 + src/coffee/MassUpload.coffee | 301 -- src/coffee/MassUpload/FileDeleter.coffee | 54 - src/coffee/MassUpload/FileInfo.coffee | 21 - src/coffee/MassUpload/FileLister.coffee | 52 - src/coffee/MassUpload/FileUploader.coffee | 83 - src/coffee/MassUpload/State.coffee | 62 - src/coffee/MassUpload/Upload.coffee | 112 - src/coffee/MassUpload/UploadCollection.coffee | 219 - src/coffee/MassUpload/UploadProgress.coffee | 69 - .../MassUpload/views/AbstractProgress.coffee | 75 - .../MassUpload/views/ListFilesProgress.coffee | 8 - src/coffee/MassUpload/views/MassUpload.coffee | 34 - .../MassUpload/views/UploadCollection.coffee | 188 - .../MassUpload/views/UploadProgress.coffee | 9 - .../MassUpload/views/humanReadableSize.coffee | 22 - src/coffee/index.coffee | 5 - src/coffee/mass-upload.coffee | 2 - src/js/MassUpload.js | 342 -- src/js/MassUpload/FileDeleter.js | 55 - src/js/MassUpload/FileInfo.js | 21 - src/js/MassUpload/FileLister.js | 52 - src/js/MassUpload/FileUploader.js | 72 - src/js/MassUpload/State.js | 69 - src/js/MassUpload/Upload.js | 87 - src/js/MassUpload/UploadCollection.js | 247 - src/js/MassUpload/UploadProgress.js | 81 - src/js/MassUpload/views/AbstractProgress.js | 69 - src/js/MassUpload/views/ListFilesProgress.js | 9 - src/js/MassUpload/views/MassUpload.js | 45 - src/js/MassUpload/views/UploadCollection.js | 181 - src/js/MassUpload/views/UploadProgress.js | 12 - src/js/MassUpload/views/humanReadableSize.js | 17 - src/js/index.js | 3 - src/js/mass-upload.js | 3 - test/MassUpload/FileDeleterSpec.coffee | 63 + test/MassUpload/FileInfoSpec.coffee | 51 + test/MassUpload/FileListerSpec.coffee | 73 + test/MassUpload/FileUploaderSpec.coffee | 93 + test/MassUpload/StateSpec.coffee | 98 + test/MassUpload/UploadCollectionSpec.coffee | 214 + test/MassUpload/UploadProgressSpec.coffee | 102 + test/MassUpload/UploadSpec.coffee | 142 + test/MassUploadSpec.coffee | 339 ++ test/coffee/MassUpload/FileDeleterSpec.coffee | 62 - test/coffee/MassUpload/FileInfoSpec.coffee | 50 - test/coffee/MassUpload/FileListerSpec.coffee | 72 - .../coffee/MassUpload/FileUploaderSpec.coffee | 92 - test/coffee/MassUpload/StateSpec.coffee | 97 - .../MassUpload/UploadCollectionSpec.coffee | 212 - .../MassUpload/UploadProgressSpec.coffee | 100 - test/coffee/MassUpload/UploadSpec.coffee | 141 - test/coffee/MassUploadSpec.coffee | 335 -- test/init.coffee | 6 + test/karma.conf.js | 27 +- test/test-main.js | 33 - 87 files changed, 6847 insertions(+), 6655 deletions(-) delete mode 100644 Gruntfile.coffee delete mode 100644 bower.json delete mode 100644 demo/coffee/main.coffee delete mode 100644 dist/mass-upload.js delete mode 100644 dist/mass-upload.min.js delete mode 100644 dist/mass-upload.no-require.js delete mode 100644 dist/mass-upload.no-require.min.js create mode 100644 gulpfile.coffee create mode 100644 gulpfile.js create mode 100644 js-mass-upload.js create mode 100644 js-mass-upload.min.js create mode 100644 src/MassUpload.coffee create mode 100644 src/MassUpload/FileDeleter.coffee create mode 100644 src/MassUpload/FileInfo.coffee create mode 100644 src/MassUpload/FileLister.coffee create mode 100644 src/MassUpload/FileUploader.coffee create mode 100644 src/MassUpload/State.coffee create mode 100644 src/MassUpload/Upload.coffee create mode 100644 src/MassUpload/UploadCollection.coffee create mode 100644 src/MassUpload/UploadProgress.coffee create mode 100644 src/MassUpload/views/AbstractProgress.coffee create mode 100644 src/MassUpload/views/ListFilesProgress.coffee create mode 100644 src/MassUpload/views/MassUpload.coffee create mode 100644 src/MassUpload/views/UploadCollection.coffee create mode 100644 src/MassUpload/views/UploadProgress.coffee create mode 100644 src/MassUpload/views/humanReadableSize.coffee delete mode 100644 src/coffee/MassUpload.coffee delete mode 100644 src/coffee/MassUpload/FileDeleter.coffee delete mode 100644 src/coffee/MassUpload/FileInfo.coffee delete mode 100644 src/coffee/MassUpload/FileLister.coffee delete mode 100644 src/coffee/MassUpload/FileUploader.coffee delete mode 100644 src/coffee/MassUpload/State.coffee delete mode 100644 src/coffee/MassUpload/Upload.coffee delete mode 100644 src/coffee/MassUpload/UploadCollection.coffee delete mode 100644 src/coffee/MassUpload/UploadProgress.coffee delete mode 100644 src/coffee/MassUpload/views/AbstractProgress.coffee delete mode 100644 src/coffee/MassUpload/views/ListFilesProgress.coffee delete mode 100644 src/coffee/MassUpload/views/MassUpload.coffee delete mode 100644 src/coffee/MassUpload/views/UploadCollection.coffee delete mode 100644 src/coffee/MassUpload/views/UploadProgress.coffee delete mode 100644 src/coffee/MassUpload/views/humanReadableSize.coffee delete mode 100644 src/coffee/index.coffee delete mode 100644 src/coffee/mass-upload.coffee delete mode 100644 src/js/MassUpload.js delete mode 100644 src/js/MassUpload/FileDeleter.js delete mode 100644 src/js/MassUpload/FileInfo.js delete mode 100644 src/js/MassUpload/FileLister.js delete mode 100644 src/js/MassUpload/FileUploader.js delete mode 100644 src/js/MassUpload/State.js delete mode 100644 src/js/MassUpload/Upload.js delete mode 100644 src/js/MassUpload/UploadCollection.js delete mode 100644 src/js/MassUpload/UploadProgress.js delete mode 100644 src/js/MassUpload/views/AbstractProgress.js delete mode 100644 src/js/MassUpload/views/ListFilesProgress.js delete mode 100644 src/js/MassUpload/views/MassUpload.js delete mode 100644 src/js/MassUpload/views/UploadCollection.js delete mode 100644 src/js/MassUpload/views/UploadProgress.js delete mode 100644 src/js/MassUpload/views/humanReadableSize.js delete mode 100644 src/js/index.js delete mode 100644 src/js/mass-upload.js create mode 100644 test/MassUpload/FileDeleterSpec.coffee create mode 100644 test/MassUpload/FileInfoSpec.coffee create mode 100644 test/MassUpload/FileListerSpec.coffee create mode 100644 test/MassUpload/FileUploaderSpec.coffee create mode 100644 test/MassUpload/StateSpec.coffee create mode 100644 test/MassUpload/UploadCollectionSpec.coffee create mode 100644 test/MassUpload/UploadProgressSpec.coffee create mode 100644 test/MassUpload/UploadSpec.coffee create mode 100644 test/MassUploadSpec.coffee delete mode 100644 test/coffee/MassUpload/FileDeleterSpec.coffee delete mode 100644 test/coffee/MassUpload/FileInfoSpec.coffee delete mode 100644 test/coffee/MassUpload/FileListerSpec.coffee delete mode 100644 test/coffee/MassUpload/FileUploaderSpec.coffee delete mode 100644 test/coffee/MassUpload/StateSpec.coffee delete mode 100644 test/coffee/MassUpload/UploadCollectionSpec.coffee delete mode 100644 test/coffee/MassUpload/UploadProgressSpec.coffee delete mode 100644 test/coffee/MassUpload/UploadSpec.coffee delete mode 100644 test/coffee/MassUploadSpec.coffee create mode 100644 test/init.coffee delete mode 100644 test/test-main.js diff --git a/.gitignore b/.gitignore index 05a4c9b..f83d174 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,4 @@ -bower_components/ node_modules/ demo/js demo/css -test/js .DS_Store diff --git a/Gruntfile.coffee b/Gruntfile.coffee deleted file mode 100644 index fe689a7..0000000 --- a/Gruntfile.coffee +++ /dev/null @@ -1,135 +0,0 @@ -module.exports = (grunt) -> - grunt.initConfig - coffee: - options: - bare: true - flatten: false - - demo: - expand: true - cwd: 'demo/coffee' - src: [ '**/*.coffee' ] - dest: 'demo/js' - ext: '.js' - - src: - expand: true - cwd: 'src/coffee' - src: [ '**/*.coffee' ] - dest: 'src/js' - ext: '.js' - - test: - expand: true - cwd: 'test/coffee' - src: [ '**/*.coffee' ] - dest: 'test/js' - ext: '.js' - - less: - demo: - files: - 'demo/css/style.css': 'demo/less/style.less' - - connect: - server: - options: - port: 8080 - base: '.' - - requirejs: - options: - baseUrl: 'src/js/' - exclude: [ 'backbone', 'underscore', 'jquery' ] - paths: - backbone: '../../bower_components/backbone/backbone' - underscore: '../../bower_components/underscore/underscore' - jquery: '../../bower_components/jquery/jquery' - shim: - backbone: - deps: [ 'jquery', 'underscore' ] - exports: 'Backbone' - jquery: - exports: '$' - underscore: - exports: '_' - - development: - options: - name: 'mass-upload' - optimize: 'none' - out: 'dist/mass-upload.js' - - minified: - options: - name: 'mass-upload' - optimize: 'uglify2' - out: 'dist/mass-upload.min.js' - - almond: - options: - name: 'index' - optimize: 'none' - almond: true - wrap: true - out: 'dist/mass-upload.no-require.js' - - almond_minified: - options: - name: 'index' - optimize: 'uglify2' - almond: true - wrap: true - out: 'dist/mass-upload.no-require.min.js' - - karma: - options: - configFile: 'test/karma.conf.js' - unit: - background: true - continuous: - singleRun: true - - watch: - options: - spawn: false - coffee: - files: [ 'src/coffee/**/*.coffee' ] - tasks: [ 'coffee:src', 'karma:unit:run' ] - 'coffee-demo': - files: [ 'demo/coffee/**/*.coffee' ] - tasks: [ 'coffee:demo' ] - 'coffee-test': - files: [ 'test/coffee/**/*.coffee' ] - tasks: [ 'coffee:test', 'karma:unit:run' ] - 'less-demo': - files: [ 'demo/less/**/*.less' ] - tasks: [ 'less:demo' ] - - grunt.loadNpmTasks('grunt-contrib-connect') - grunt.loadNpmTasks('grunt-contrib-coffee') - grunt.loadNpmTasks('grunt-contrib-less') - grunt.loadNpmTasks('grunt-contrib-watch') - grunt.loadNpmTasks('grunt-requirejs') - grunt.loadNpmTasks('grunt-karma') - - # Only rewrite changed files on watch - grunt.event.on 'watch', (action, filepath) -> - if filepath.indexOf('.coffee') == filepath.length - 7 && filepath.length > 7 - srcPath = grunt.config('coffee.src.cwd') - testPath = grunt.config('coffee.test.cwd') - demoPath = grunt.config('coffee.demo.cwd') - if filepath.indexOf(srcPath) == 0 - grunt.config('coffee.src.src', filepath.replace(srcPath, '.')) - else if filepath.indexOf(testPath) == 0 - grunt.config('coffee.test.src', filepath.replace(testPath, '.')) - else if filepath.indexOf(demoPath) == 0 - grunt.config('coffee.demo.src', filepath.replace(demoPath, '.')) - - # karma:unit takes a moment to spin up - grunt.registerTask 'wait-for-karma', 'Wait until Karma server is running', -> - setTimeout(@async(), 3000) - - grunt.registerTask('default', [ 'coffee:src', 'requirejs' ]) - grunt.registerTask('test', [ 'coffee', 'karma:continuous' ]) - grunt.registerTask('develop', [ 'coffee', 'less:demo', 'karma:unit', 'wait-for-karma', 'karma:unit:run', 'connect:server', 'watch' ]) diff --git a/README.md b/README.md index b5ee83b..9d2b6a1 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,12 @@ First, include the library. (It depends on [Backbone](http://backbonejs.org).) Y require([ 'path/to/mass-upload' ], function(MassUpload) { ... }); ``` +Or you can use [Browserify](http://browserify.org/) or plain Node `require`: + +```javascript +var MassUpload = require('js-mass-upload'); +``` + Or, you can go the old-fashioned route in your HTML: ```html @@ -232,13 +238,10 @@ To build and contribute: 1. Install [NodeJS](http://nodejs.org/) 2. Clone this repository: `git clone https://github.com/overview/js-mass-upload.git` 3. `npm install` in this directory -4. `bower install` in this directory -5. `grunt develop` to start developing. -6. Write tests in `test/coffee`. In the terminal that's running `grunt develop`, you'll see new failures. -7. Once you've created a test failure, edit code in `src/coffee`, until the terminal that's running `grunt develop` comes up green. -8. Browse to http://localhost:8080/demo/ to see your code in action. -9. Run `grunt` to populate the `dist/` directory. -10. commit and create a pull request. +4. `gulp` to build +5. `gulp test` to unit-test +6. Add a test; return to step 4; make test pass; return to step 4 +7. git commit and create a pull request License ------- diff --git a/bower.json b/bower.json deleted file mode 100644 index baea417..0000000 --- a/bower.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "js-mass-upload", - "version": "0.0.7", - "main": "mass-upload.js", - "ignore": [ - "**/.*", - "bower_components", - "node_modules", - "src/coffee", - "spec", - "Gruntfile.js", - "package.json" - ], - "dependencies": { - "backbone": "~1.0.0", - "underscore": "~1.5.1" - }, - "devDependencies": { - "jquery": "~2.0.3" - } -} diff --git a/demo/coffee/app.coffee b/demo/coffee/app.coffee index 443579e..912a5e1 100644 --- a/demo/coffee/app.coffee +++ b/demo/coffee/app.coffee @@ -1,14 +1,21 @@ -define [ 'jquery', 'mass-upload', 'upload-logic', 'MassUpload/views/MassUpload' ], ($, MassUpload, uploadLogic, MassUploadView) -> - options = $.extend({ - }, uploadLogic) +$ = require('jquery') +Backbone = require('backbone') - massUpload = new MassUpload(options) +Backbone.$ = $ - new MassUploadView(model: massUpload, el: $('.mass-upload')) +MassUpload = require('../../js-mass-upload') +uploadLogic = require('./upload-logic') +MassUploadView = require('../../src/MassUpload/views/MassUpload') - $networkIsWorking = $('#network-is-working') - $networkIsWorking.change -> - value = $networkIsWorking.prop('checked') - uploadLogic.toggleWorking(value) +options = $.extend({}, uploadLogic) - massUpload.fetchFileInfosFromServer() +massUpload = new MassUpload(options) + +new MassUploadView(model: massUpload, el: $('.mass-upload')) + +$networkIsWorking = $('#network-is-working') +$networkIsWorking.change -> + value = $networkIsWorking.prop('checked') + uploadLogic.toggleWorking(value) + +massUpload.fetchFileInfosFromServer() diff --git a/demo/coffee/main.coffee b/demo/coffee/main.coffee deleted file mode 100644 index 5d9b9de..0000000 --- a/demo/coffee/main.coffee +++ /dev/null @@ -1,20 +0,0 @@ -requirejs.config - baseUrl: '/demo/js' - paths: - backbone: '../../bower_components/backbone/backbone' - underscore: '../../bower_components/underscore/underscore' - jquery: '../../bower_components/jquery/jquery' - 'mass-upload': '../../src/js/mass-upload' - map: - '*': - MassUpload: '../../src/js/MassUpload' - shim: - backbone: - deps: [ 'jquery', 'underscore' ] - exports: 'Backbone' - jquery: - exports: '$' - underscore: - exports: '_' - -require [ 'app' ], -> diff --git a/demo/coffee/upload-logic.coffee b/demo/coffee/upload-logic.coffee index 6fe38b5..bfb1f54 100644 --- a/demo/coffee/upload-logic.coffee +++ b/demo/coffee/upload-logic.coffee @@ -1,47 +1,47 @@ -define -> - date1 = new Date('Mon, 13 Aug 2013 09:29:16 -0400') - date2 = new Date('Mon, 14 Aug 2013 09:29:16 -0400') - date3 = new Date('Mon, 15 Aug 2013 09:29:16 -0400') - serverFiles = [ - { name: 'file1.txt', loaded: 2000, total: 10000, lastModifiedDate: date1 } - { name: 'file2.txt', loaded: 3000, total: 20000, lastModifiedDate: date2 } - { name: 'file3.txt', loaded: 4000, total: 30000, lastModifiedDate: date3 } - ] - - networkIsWorking = true # when false, all ticks fail - - sendAsyncError = (error, message) -> - window.setTimeout((-> error(message)), 50) - - tickListFilesAtBytes = (bytes, progress, success, error) -> - if !networkIsWorking - sendAsyncError(error, 'network is broken') +date1 = new Date('Mon, 13 Aug 2013 09:29:16 -0400') +date2 = new Date('Mon, 14 Aug 2013 09:29:16 -0400') +date3 = new Date('Mon, 15 Aug 2013 09:29:16 -0400') +serverFiles = [ + { name: 'file1.txt', loaded: 2000, total: 10000, lastModifiedDate: date1 } + { name: 'file2.txt', loaded: 3000, total: 20000, lastModifiedDate: date2 } + { name: 'file3.txt', loaded: 4000, total: 30000, lastModifiedDate: date3 } +] + +networkIsWorking = true # when false, all ticks fail + +sendAsyncError = (error, message) -> + window.setTimeout((-> error(message)), 50) + +tickListFilesAtBytes = (bytes, progress, success, error) -> + if !networkIsWorking + sendAsyncError(error, 'network is broken') + else + total = 1000 + increment = 100 + timeout = 100 + + if bytes >= total + progress({ loaded: total, total: total }) + success(serverFiles) else - total = 1000 - increment = 100 - timeout = 100 - - if bytes >= total - progress({ loaded: total, total: total }) - success(serverFiles) - else - progress({ loaded: bytes, total: total }) - window.setTimeout((-> tickListFilesAtBytes(bytes + increment, progress, success, error)), timeout) - - tickUploadFileAtByte = (file, bytes, progress, success, error) -> - if !networkIsWorking - sendAsyncError(error, 'network is broken') + progress({ loaded: bytes, total: total }) + window.setTimeout((-> tickListFilesAtBytes(bytes + increment, progress, success, error)), timeout) + +tickUploadFileAtByte = (file, bytes, progress, success, error) -> + if !networkIsWorking + sendAsyncError(error, 'network is broken') + else + increment = 50000 + timeout = 500 + + if bytes >= file.size + progress({ loaded: file.size, total: file.size }) + success() else - increment = 50000 - timeout = 500 - - if bytes >= file.size - progress({ loaded: file.size, total: file.size }) - success() - else - progress({ loaded: bytes, total: file.size }) - window.setTimeout((-> tickUploadFileAtByte(file, bytes + increment, progress, success, error)), timeout) + progress({ loaded: bytes, total: file.size }) + window.setTimeout((-> tickUploadFileAtByte(file, bytes + increment, progress, success, error)), timeout) +module.exports = # Returns three dummy files, taking about a second doListFiles: (progress, success, error) -> tickListFilesAtBytes(0, progress, success, error) diff --git a/demo/index.html b/demo/index.html index 92f6aed..3681416 100644 --- a/demo/index.html +++ b/demo/index.html @@ -10,5 +10,5 @@

MassUpload demo

- + diff --git a/dist/mass-upload.js b/dist/mass-upload.js deleted file mode 100644 index 0405f0e..0000000 --- a/dist/mass-upload.js +++ /dev/null @@ -1,1039 +0,0 @@ - -define('MassUpload/FileInfo',[],function() { - var FileInfo; - FileInfo = (function() { - function FileInfo(name, lastModifiedDate, total, loaded) { - this.name = name; - this.lastModifiedDate = lastModifiedDate; - this.total = total; - this.loaded = loaded; - } - - return FileInfo; - - })(); - FileInfo.fromJson = function(obj) { - return new FileInfo(obj.name, new Date(obj.lastModifiedDate), obj.total, obj.loaded); - }; - FileInfo.fromFile = function(obj) { - return new FileInfo(obj.webkitRelativePath || obj.name, obj.lastModifiedDate, obj.size, 0); - }; - return FileInfo; -}); - -define('MassUpload/Upload',['underscore', 'backbone', './FileInfo'], function(_, Backbone, FileInfo) { - var Upload; - return Upload = (function() { - Upload.prototype = Object.create(Backbone.Events); - - Upload.prototype.defaults = { - file: null, - fileInfo: null, - error: null, - uploading: false, - deleting: false - }; - - function Upload(attributes) { - var _ref, _ref1, _ref2; - this.file = (_ref = attributes.file) != null ? _ref : null; - this.fileInfo = (_ref1 = attributes.fileInfo) != null ? _ref1 : null; - this.error = (_ref2 = attributes.error) != null ? _ref2 : null; - this.uploading = attributes.uploading || false; - this.deleting = attributes.deleting || false; - this.id = this.file != null ? this.file.webkitRelativePath || this.file.name : this.fileInfo.name; - this.attributes = this; - } - - Upload.prototype.get = function(attr) { - return this[attr]; - }; - - Upload.prototype.set = function(attrs) { - var k, v; - this._previousAttributes = new Upload(this); - for (k in attrs) { - v = attrs[k]; - this[k] = v; - } - this.trigger('change', this); - return this._previousAttributes = null; - }; - - Upload.prototype.previousAttributes = function() { - return this._previousAttributes; - }; - - Upload.prototype.size = function() { - var _ref; - return this._size != null ? this._size : this._size = (_ref = this.file) != null ? _ref.size : void 0; - }; - - Upload.prototype.lastModifiedDate = function() { - var _ref; - return this._lastModifiedDate != null ? this._lastModifiedDate : this._lastModifiedDate = (_ref = this.file) != null ? _ref.lastModifiedDate : void 0; - }; - - Upload.prototype.updateWithProgress = function(progressEvent) { - var fileInfo; - fileInfo = new FileInfo(this.id, this.lastModifiedDate(), progressEvent.total, progressEvent.loaded); - return this.set({ - fileInfo: fileInfo - }); - }; - - Upload.prototype.getProgress = function() { - if ((this.fileInfo != null) && !this.hasConflict()) { - return { - loaded: this.fileInfo.loaded, - total: this.fileInfo.total - }; - } else if (this.file != null) { - return { - loaded: 0, - total: this.size() - }; - } - }; - - Upload.prototype.isFullyUploaded = function() { - return (this.fileInfo != null) && (this.error == null) && !this.uploading && !this.deleting && this.fileInfo.loaded === this.fileInfo.total; - }; - - Upload.prototype.hasConflict = function() { - return (this.fileInfo != null) && (this.file != null) && (this.fileInfo.name !== this.id || this.fileInfo.total !== this.size() || this.fileInfo.lastModifiedDate.getTime() !== this.lastModifiedDate().getTime()); - }; - - return Upload; - - })(); -}); - -define('MassUpload/UploadCollection',['backbone', './Upload'], function(Backbone, Upload) { - var UploadCollection, UploadPriorityQueue; - UploadPriorityQueue = (function() { - function UploadPriorityQueue() { - this._clear(); - } - - UploadPriorityQueue.prototype._clear = function() { - this.deleting = []; - this.uploading = []; - this.unfinished = []; - return this.unstarted = []; - }; - - UploadPriorityQueue.prototype.uploadAttributesToState = function(uploadAttributes) { - var ret; - ret = uploadAttributes.error != null ? null : uploadAttributes.deleting ? 'deleting' : uploadAttributes.uploading ? 'uploading' : (uploadAttributes.file != null) && (uploadAttributes.fileInfo != null) && uploadAttributes.fileInfo.loaded < uploadAttributes.fileInfo.total ? 'unfinished' : (uploadAttributes.file != null) && (uploadAttributes.fileInfo == null) ? 'unstarted' : null; - return ret; - }; - - UploadPriorityQueue.prototype.addBatch = function(uploads) { - var state, upload, _i, _len; - for (_i = 0, _len = uploads.length; _i < _len; _i++) { - upload = uploads[_i]; - state = this.uploadAttributesToState(upload.attributes); - if (state != null) { - this[state].push(upload); - } - } - return void 0; - }; - - UploadPriorityQueue.prototype._removeUploadFromArray = function(upload, array) { - var idx; - idx = array.indexOf(upload); - if (idx >= 0) { - return array.splice(idx, 1); - } - }; - - UploadPriorityQueue.prototype.remove = function(upload) { - var state; - state = this.uploadAttributesToState(upload.attributes); - if (state != null) { - return this._removeUploadFromArray(upload.attributes, this[state]); - } - }; - - UploadPriorityQueue.prototype.change = function(upload) { - var newState, prevState; - prevState = this.uploadAttributesToState(upload.previousAttributes()); - newState = this.uploadAttributesToState(upload.attributes); - if (prevState !== newState) { - if (prevState != null) { - this._removeUploadFromArray(upload, this[prevState]); - } - if (newState != null) { - return this[newState].push(upload); - } - } - }; - - UploadPriorityQueue.prototype.reset = function(uploads) { - if (uploads == null) { - uploads = []; - } - this._clear(); - return this.addBatch(uploads); - }; - - UploadPriorityQueue.prototype.next = function() { - var _ref, _ref1, _ref2, _ref3; - return (_ref = (_ref1 = (_ref2 = (_ref3 = this.deleting[0]) != null ? _ref3 : this.uploading[0]) != null ? _ref2 : this.unfinished[0]) != null ? _ref1 : this.unstarted[0]) != null ? _ref : null; - }; - - return UploadPriorityQueue; - - })(); - return UploadCollection = (function() { - UploadCollection.prototype = Object.create(Backbone.Events); - - function UploadCollection() { - this.models = []; - this._priorityQueue = new UploadPriorityQueue(); - this.reset([]); - } - - UploadCollection.prototype.each = function(func, context) { - return this.models.forEach(func, context); - }; - - UploadCollection.prototype.map = function(func, context) { - return this.models.map(func, context); - }; - - UploadCollection.prototype._prepareModel = function(upload) { - if (upload instanceof Upload) { - return upload; - } else { - return new Upload(upload); - } - }; - - UploadCollection.prototype.reset = function(uploads) { - var upload, _i, _j, _len, _len1, _ref, _ref1; - _ref = this.models; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - upload = _ref[_i]; - upload.off('all', this._onUploadEvent, this); - } - this.models = (function() { - var _j, _len1, _ref1, _results; - _ref1 = uploads != null ? uploads : []; - _results = []; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - upload = _ref1[_j]; - _results.push(this._prepareModel(upload)); - } - return _results; - }).call(this); - this.length = this.models.length; - this._idToModel = {}; - _ref1 = this.models; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - upload = _ref1[_j]; - upload.on('all', this._onUploadEvent, this); - this._idToModel[upload.id] = upload; - } - this._priorityQueue.reset(this.models); - return this.trigger('reset', this); - }; - - UploadCollection.prototype.get = function(id) { - var _ref; - return (_ref = this._idToModel[id]) != null ? _ref : null; - }; - - UploadCollection.prototype.forFile = function(file) { - return this.get(file.webkitRelativePath || file.name); - }; - - UploadCollection.prototype.forFileInfo = function(fileInfo) { - return this.get(fileInfo.name); - }; - - UploadCollection.prototype.addFiles = function(files) { - var file, uploads; - uploads = (function() { - var _i, _len, _results; - _results = []; - for (_i = 0, _len = files.length; _i < _len; _i++) { - file = files[_i]; - _results.push(new Upload({ - file: file - })); - } - return _results; - })(); - return this._addWithMerge(uploads); - }; - - UploadCollection.prototype.addFileInfos = function(fileInfos) { - var fileInfo, uploads; - uploads = (function() { - var _i, _len, _results; - _results = []; - for (_i = 0, _len = fileInfos.length; _i < _len; _i++) { - fileInfo = fileInfos[_i]; - _results.push(new Upload({ - fileInfo: fileInfo - })); - } - return _results; - })(); - return this._addWithMerge(uploads); - }; - - UploadCollection.prototype.next = function() { - return this._priorityQueue.next(); - }; - - UploadCollection.prototype.add = function(uploadOrUploads) { - if (uploadOrUploads.length != null) { - return this.addBatch(uploadOrUploads); - } else { - return this.addBatch([uploadOrUploads]); - } - }; - - UploadCollection.prototype.addBatch = function(uploads) { - var upload, _i, _j, _len, _len1; - for (_i = 0, _len = uploads.length; _i < _len; _i++) { - upload = uploads[_i]; - this._idToModel[upload.id] = upload; - upload.on('all', this._onUploadEvent, this); - this.models.push(upload); - } - this.length += uploads.length; - this._priorityQueue.addBatch(uploads); - for (_j = 0, _len1 = uploads.length; _j < _len1; _j++) { - upload = uploads[_j]; - this.trigger('add', upload); - } - return this.trigger('add-batch', uploads); - }; - - UploadCollection.prototype._onUploadEvent = function(event, model, collection, options) { - if (event !== 'add' && event !== 'remove') { - this.trigger.apply(this, arguments); - } - if (event === 'change') { - return this._priorityQueue.change(model); - } - }; - - UploadCollection.prototype._addWithMerge = function(uploads) { - var existingUpload, file, fileInfo, toAdd, upload, _i, _len; - toAdd = []; - for (_i = 0, _len = uploads.length; _i < _len; _i++) { - upload = uploads[_i]; - if ((existingUpload = this.get(upload.id)) != null) { - file = upload.get('file'); - fileInfo = upload.get('fileInfo'); - if (file != null) { - existingUpload.set({ - file: file - }); - } - if (fileInfo != null) { - existingUpload.set({ - fileInfo: fileInfo - }); - } - } else { - toAdd.push(upload); - } - } - if (toAdd.length) { - this.add(toAdd); - } - return void 0; - }; - - return UploadCollection; - - })(); -}); - -define('MassUpload/FileLister',[],function() { - var FileLister; - return FileLister = (function() { - function FileLister(doListFiles, callbacks) { - this.doListFiles = doListFiles; - this.callbacks = callbacks; - this.running = false; - } - - FileLister.prototype.run = function() { - var _base, - _this = this; - if (this.running) { - throw 'already running'; - } - this.running = true; - if (typeof (_base = this.callbacks).onStart === "function") { - _base.onStart(); - } - return this.doListFiles((function(progressEvent) { - var _base1; - return typeof (_base1 = _this.callbacks).onProgress === "function" ? _base1.onProgress(progressEvent) : void 0; - }), (function(fileInfos) { - return _this._onSuccess(fileInfos); - }), (function(errorDetail) { - return _this._onError(errorDetail); - })); - }; - - FileLister.prototype._onSuccess = function(fileInfos) { - var _base; - if (typeof (_base = this.callbacks).onSuccess === "function") { - _base.onSuccess(fileInfos); - } - return this._onStop(); - }; - - FileLister.prototype._onError = function(errorDetail) { - this.callbacks.onError(errorDetail); - return this._onStop(); - }; - - FileLister.prototype._onStop = function() { - var _base; - this.running = false; - return typeof (_base = this.callbacks).onStop === "function" ? _base.onStop() : void 0; - }; - - return FileLister; - - })(); -}); - -define('MassUpload/FileUploader',['./FileInfo'], function(FileInfo) { - var FileUploader; - return FileUploader = (function() { - function FileUploader(doUpload, callbacks) { - this.doUpload = doUpload; - this.callbacks = callbacks; - this._file = null; - this._abortCallback = null; - this._aborting = false; - } - - FileUploader.prototype.run = function(file) { - var _base, - _this = this; - if (this._file != null) { - throw 'already running'; - } - this._file = file; - if (typeof (_base = this.callbacks).onStart === "function") { - _base.onStart(this._file); - } - return this._abortCallback = this.doUpload(file, (function(progressEvent) { - return _this._onProgress(file, progressEvent); - }), (function() { - return _this._onSuccess(file); - }), (function(errorDetail) { - return _this._onError(file, errorDetail); - })); - }; - - FileUploader.prototype.abort = function() { - if (this._file && !this._aborting) { - this._aborting = true; - if (typeof this._abortCallback === 'function') { - return this._abortCallback(); - } - } - }; - - FileUploader.prototype._onProgress = function(file, progressEvent) { - var _base; - return typeof (_base = this.callbacks).onProgress === "function" ? _base.onProgress(file, progressEvent) : void 0; - }; - - FileUploader.prototype._onSuccess = function(file) { - var _base; - if (typeof (_base = this.callbacks).onSuccess === "function") { - _base.onSuccess(file); - } - return this._onStop(file); - }; - - FileUploader.prototype._onError = function(file, errorDetail) { - var _base; - if (typeof (_base = this.callbacks).onError === "function") { - _base.onError(file, errorDetail); - } - return this._onStop(file); - }; - - FileUploader.prototype._onStop = function(file) { - var _base; - this._file = null; - this._abortCallback = null; - this._aborting = false; - return typeof (_base = this.callbacks).onStop === "function" ? _base.onStop(file) : void 0; - }; - - return FileUploader; - - })(); -}); - -define('MassUpload/FileDeleter',[],function() { - var FileDeleter; - return FileDeleter = (function() { - function FileDeleter(doDeleteFile, callbacks) { - this.doDeleteFile = doDeleteFile; - this.callbacks = callbacks != null ? callbacks : {}; - this.running = false; - } - - FileDeleter.prototype.run = function(fileInfo) { - var _base, - _this = this; - if (this.running) { - throw 'already running'; - } - this.running = true; - if (typeof (_base = this.callbacks).onStart === "function") { - _base.onStart(fileInfo); - } - return this.doDeleteFile(fileInfo, (function() { - return _this._onSuccess(fileInfo); - }), (function(errorDetail) { - return _this._onError(fileInfo, errorDetail); - })); - }; - - FileDeleter.prototype._onSuccess = function(fileInfo) { - var _base; - if (typeof (_base = this.callbacks).onSuccess === "function") { - _base.onSuccess(fileInfo); - } - return this._onStop(fileInfo); - }; - - FileDeleter.prototype._onError = function(fileInfo, errorDetail) { - var _base; - if (typeof (_base = this.callbacks).onError === "function") { - _base.onError(fileInfo, errorDetail); - } - return this._onStop(fileInfo); - }; - - FileDeleter.prototype._onStop = function(fileInfo) { - var _base; - this.running = false; - if (typeof (_base = this.callbacks).onStop === "function") { - _base.onStop(fileInfo); - } - return void 0; - }; - - return FileDeleter; - - })(); -}); - -define('MassUpload/State',[],function() { - var State; - return State = (function() { - function State(attrs) { - var _ref, _ref1, _ref2, _ref3; - if (attrs == null) { - attrs = {}; - } - this.loaded = (_ref = attrs.loaded) != null ? _ref : 0; - this.total = (_ref1 = attrs.total) != null ? _ref1 : 0; - this.status = (_ref2 = attrs.status) != null ? _ref2 : 'waiting'; - this.errors = (_ref3 = attrs.errors) != null ? _ref3 : []; - } - - State.prototype._extend = function(attrs) { - var _ref, _ref1, _ref2, _ref3; - return new State({ - loaded: (_ref = attrs.loaded) != null ? _ref : this.loaded, - total: (_ref1 = attrs.total) != null ? _ref1 : this.total, - status: (_ref2 = attrs.status) != null ? _ref2 : this.status, - errors: (_ref3 = attrs.errors) != null ? _ref3 : this.errors - }); - }; - - State.prototype.isComplete = function() { - return this.total && this.loaded === this.total && this.status === 'waiting' && !this.errors.length && true || false; - }; - - State.prototype.withTotal = function(total) { - return this._extend({ - total: total - }); - }; - - State.prototype.withLoaded = function(loaded) { - return this._extend({ - loaded: loaded - }); - }; - - State.prototype.withStatus = function(status) { - return this._extend({ - status: status - }); - }; - - State.prototype.withAnError = function(error) { - var newErrors; - newErrors = this.errors.slice(0); - newErrors.push(error); - return this._extend({ - errors: newErrors - }); - }; - - State.prototype.withoutAnError = function(error) { - var index, newErrors; - newErrors = this.errors.slice(0); - index = newErrors.indexOf(error); - newErrors.splice(index, 1); - return this._extend({ - errors: newErrors - }); - }; - - return State; - - })(); -}); - -define('MassUpload/UploadProgress',['backbone'], function(Backbone) { - return Backbone.Model.extend({ - defaults: { - loaded: 0, - total: 0 - }, - initialize: function() { - var collection; - collection = this.get('uploadCollection'); - if (collection == null) { - throw 'Must initialize UploadProgress with `uploadCollection`, an UploadCollection'; - } - this._idToLastKnownProgress = {}; - return this._updateAndStartListening(); - }, - _adjust: function(dLoaded, dTotal) { - return this.set({ - loaded: this.get('loaded') + dLoaded, - total: this.get('total') + dTotal - }); - }, - add: function(model) { - var progress; - progress = model.getProgress(); - this._adjust(progress.loaded, progress.total); - return this._idToLastKnownProgress[model.id] = progress; - }, - reset: function(collection) { - var idToLastKnownProgress, loaded, model, progress, total, _i, _len, _ref; - idToLastKnownProgress = this._idToLastKnownProgress = {}; - loaded = 0; - total = 0; - _ref = collection.models; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - model = _ref[_i]; - progress = model.getProgress(); - idToLastKnownProgress[model.id] = progress; - loaded += progress.loaded; - total += progress.total; - } - return this.set({ - loaded: loaded, - total: total - }); - }, - remove: function(model) { - var progress; - progress = model.getProgress(); - this._adjust(-progress.loaded, -progress.total); - return this._idToLastKnownProgress[model.id] = progress; - }, - change: function(model) { - var newProgress, oldProgress; - oldProgress = this._idToLastKnownProgress[model.id]; - if (oldProgress != null) { - newProgress = model.getProgress(); - this._adjust(newProgress.loaded - oldProgress.loaded, newProgress.total - oldProgress.total); - return this._idToLastKnownProgress[model.id] = newProgress; - } - }, - _updateAndStartListening: function() { - var collection, event, _i, _len, _ref; - collection = this.get('uploadCollection'); - _ref = ['add', 'remove', 'change', 'reset']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - event = _ref[_i]; - this.listenTo(collection, event, this[event]); - } - this.reset(collection); - return void 0; - }, - inBatch: function(callback) { - this.stopListening(this.get('uploadCollection')); - try { - return callback(); - } finally { - this._updateAndStartListening(); - } - } - }); -}); - -var __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - -define('MassUpload',['backbone', 'underscore', 'MassUpload/UploadCollection', 'MassUpload/FileLister', 'MassUpload/FileUploader', 'MassUpload/FileDeleter', 'MassUpload/State', 'MassUpload/UploadProgress'], function(Backbone, _, UploadCollection, FileLister, FileUploader, FileDeleter, State, UploadProgress) { - var MassUpload; - return MassUpload = (function(_super) { - __extends(MassUpload, _super); - - MassUpload.prototype.defaults = function() { - return { - status: 'waiting', - listFilesProgress: null, - listFilesError: null, - uploadProgress: null, - uploadErrors: [] - }; - }; - - function MassUpload(options) { - this._removedUploads = []; - MassUpload.__super__.constructor.call(this, {}, options); - } - - MassUpload.prototype.initialize = function(attributes, options) { - var resetUploadProgress, _ref, - _this = this; - this._options = options; - this.uploads = (_ref = options != null ? options.uploads : void 0) != null ? _ref : new UploadCollection(); - this._uploadProgress = new UploadProgress({ - uploadCollection: this.uploads - }); - resetUploadProgress = function() { - return _this.set({ - uploadProgress: _this._uploadProgress.pick('loaded', 'total') - }); - }; - this.listenTo(this._uploadProgress, 'change', resetUploadProgress); - resetUploadProgress(); - this.listenTo(this.uploads, 'add-batch', this._onUploadBatchAdded); - this.listenTo(this.uploads, 'change', function(upload) { - return _this._onUploadChanged(upload); - }); - this.listenTo(this.uploads, 'reset', function() { - return _this._onUploadsReset(); - }); - return this.prepare(); - }; - - MassUpload.prototype.prepare = function() { - var options, _ref, _ref1, _ref2, - _this = this; - options = this._options; - this.lister = (_ref = options != null ? options.lister : void 0) != null ? _ref : new FileLister(options.doListFiles); - this.lister.callbacks = { - onStart: function() { - return _this._onListerStart(); - }, - onProgress: function(progressEvent) { - return _this._onListerProgress(progressEvent); - }, - onSuccess: function(fileInfos) { - return _this._onListerSuccess(fileInfos); - }, - onError: function(errorDetail) { - return _this._onListerError(errorDetail); - }, - onStop: function() { - return _this._onListerStop(); - } - }; - this.uploader = (_ref1 = options != null ? options.uploader : void 0) != null ? _ref1 : new FileUploader(options.doUploadFile); - this.uploader.callbacks = { - onStart: function(file) { - return _this._onUploaderStart(file); - }, - onStop: function(file) { - return _this._onUploaderStop(file); - }, - onSuccess: function(file) { - return _this._onUploaderSuccess(file); - }, - onError: function(file, errorDetail) { - return _this._onUploaderError(file, errorDetail); - }, - onProgress: function(file, progressEvent) { - return _this._onUploaderProgress(file, progressEvent); - } - }; - this.deleter = (_ref2 = options != null ? options.deleter : void 0) != null ? _ref2 : new FileDeleter(options.doDeleteFile); - return this.deleter.callbacks = { - onStart: function(fileInfo) { - return _this._onDeleterStart(fileInfo); - }, - onSuccess: function(fileInfo) { - return _this._onDeleterSuccess(fileInfo); - }, - onError: function(fileInfo, errorDetail) { - return _this._onDeleterError(fileInfo, errorDetail); - }, - onStop: function(fileInfo) { - return _this._onDeleterStop(fileInfo); - } - }; - }; - - MassUpload.prototype.fetchFileInfosFromServer = function() { - return this.lister.run(); - }; - - MassUpload.prototype.retryListFiles = function() { - return this.fetchFileInfosFromServer(); - }; - - MassUpload.prototype.retryUpload = function(upload) { - return upload.set({ - error: null - }); - }; - - MassUpload.prototype.retryAllUploads = function() { - return this.uploads.each(function(upload) { - return upload.set({ - error: null - }); - }); - }; - - MassUpload.prototype.addFiles = function(files) { - var _this = this; - return this._uploadProgress.inBatch(function() { - return _this.uploads.addFiles(files); - }); - }; - - MassUpload.prototype.removeUpload = function(upload) { - return upload.set({ - deleting: true - }); - }; - - MassUpload.prototype.abort = function() { - var _this = this; - this.uploads.each(function(upload) { - return _this.removeUpload(upload); - }); - this.uploads.reset(); - return this.prepare(); - }; - - MassUpload.prototype._onListerStart = function() { - return this.set({ - status: 'listing-files', - listFilesError: null - }); - }; - - MassUpload.prototype._onListerProgress = function(progressEvent) { - return this.set({ - listFilesProgress: progressEvent - }); - }; - - MassUpload.prototype._onListerSuccess = function(fileInfos) { - this.uploads.addFileInfos(fileInfos); - return this._tick(); - }; - - MassUpload.prototype._onListerError = function(errorDetail) { - return this.set({ - listFilesError: errorDetail, - status: 'listing-files-error' - }); - }; - - MassUpload.prototype._onListerStop = function() {}; - - MassUpload.prototype._mergeUploadError = function(upload, prevError, curError) { - var index, newErrors; - newErrors = this.get('uploadErrors').slice(0); - index = _.sortedIndex(newErrors, { - upload: upload - }, function(x) { - return x.upload.id; - }); - if (prevError == null) { - newErrors.splice(index, 0, { - upload: upload, - error: curError - }); - } else if (curError == null) { - newErrors.splice(index, 1); - } else { - newErrors[index].error = curError; - } - return this.set({ - uploadErrors: newErrors - }); - }; - - MassUpload.prototype._onUploadBatchAdded = function(uploads) { - var error, upload, _i, _len; - for (_i = 0, _len = uploads.length; _i < _len; _i++) { - upload = uploads[_i]; - error = upload.get('error'); - if (error != null) { - this._mergeUploadError(upload, null, error); - } - } - return this._forceBestTick(); - }; - - MassUpload.prototype._onUploadChanged = function(upload) { - var deleting1, deleting2, error1, error2; - error1 = upload.previousAttributes().error; - error2 = upload.get('error'); - if (error1 !== error2) { - this._mergeUploadError(upload, error1, error2); - } - deleting1 = upload.previousAttributes().deleting; - deleting2 = upload.get('deleting'); - if (deleting2 && !deleting1) { - this._removedUploads.push(upload); - } - return this._forceBestTick(); - }; - - MassUpload.prototype._onUploadsReset = function() { - var newErrors; - newErrors = []; - this.uploads.each(function(upload) { - var error; - if ((error = upload.get('error'))) { - return newErrors.push({ - upload: upload, - error: error - }); - } - }); - this.set({ - uploadErrors: newErrors - }); - return this._tick(); - }; - - MassUpload.prototype._onUploaderStart = function(file) { - var upload; - upload = this.uploads.forFile(file); - return upload.set({ - uploading: true, - error: null - }); - }; - - MassUpload.prototype._onUploaderStop = function(file) { - var upload; - upload = this.uploads.forFile(file); - upload.set({ - uploading: false - }); - return this._tick(); - }; - - MassUpload.prototype._onUploaderProgress = function(file, progressEvent) { - var upload; - upload = this.uploads.forFile(file); - return upload.updateWithProgress(progressEvent); - }; - - MassUpload.prototype._onUploaderError = function(file, errorDetail) { - var upload; - upload = this.uploads.forFile(file); - return upload.set({ - error: errorDetail - }); - }; - - MassUpload.prototype._onUploaderSuccess = function(file) { - var upload; - upload = this.uploads.forFile(file); - return upload.updateWithProgress({ - loaded: upload.size(), - total: upload.size() - }); - }; - - MassUpload.prototype._onDeleterStart = function(fileInfo) { - return this.set({ - status: 'uploading' - }); - }; - - MassUpload.prototype._onDeleterSuccess = function(fileInfo) { - var upload; - upload = this.uploads.forFileInfo(fileInfo); - return this.uploads.remove(upload); - }; - - MassUpload.prototype._onDeleterError = function(fileInfo, errorDetail) { - var upload; - upload = this.uploads.forFileInfo(fileInfo); - return upload.set({ - error: errorDetail - }); - }; - - MassUpload.prototype._onDeleterStop = function(fileInfo) { - return this._tick(); - }; - - MassUpload.prototype._tick = function() { - var progress, status, upload; - upload = this.uploads.next(); - this._currentUpload = upload; - if (upload != null) { - if (upload.get('deleting')) { - this.deleter.run(upload.get('fileInfo')); - } else { - this.uploader.run(upload.get('file')); - } - } - status = this.get('uploadErrors').length ? 'uploading-error' : upload != null ? 'uploading' : (progress = this.get('uploadProgress'), progress.loaded === progress.total ? 'waiting' : 'waiting-error'); - return this.set({ - status: status - }); - }; - - MassUpload.prototype._forceBestTick = function() { - var upload; - upload = this.uploads.next(); - if (upload !== this._currentUpload) { - if (this._currentUpload) { - return this.uploader.abort(); - } else { - return this._tick(); - } - } - }; - - return MassUpload; - - })(Backbone.Model); -}); - -define('mass-upload',['MassUpload'], function(MassUpload) { - return MassUpload; -}); diff --git a/dist/mass-upload.min.js b/dist/mass-upload.min.js deleted file mode 100644 index 4a49869..0000000 --- a/dist/mass-upload.min.js +++ /dev/null @@ -1 +0,0 @@ -define("MassUpload/FileInfo",[],function(){var t;return t=function(){function t(t,o,e,r){this.name=t,this.lastModifiedDate=o,this.total=e,this.loaded=r}return t}(),t.fromJson=function(o){return new t(o.name,new Date(o.lastModifiedDate),o.total,o.loaded)},t.fromFile=function(o){return new t(o.webkitRelativePath||o.name,o.lastModifiedDate,o.size,0)},t}),define("MassUpload/Upload",["underscore","backbone","./FileInfo"],function(t,o,e){var r;return r=function(){function t(t){var o,e,r;this.file=null!=(o=t.file)?o:null,this.fileInfo=null!=(e=t.fileInfo)?e:null,this.error=null!=(r=t.error)?r:null,this.uploading=t.uploading||!1,this.deleting=t.deleting||!1,this.id=null!=this.file?this.file.webkitRelativePath||this.file.name:this.fileInfo.name,this.attributes=this}return t.prototype=Object.create(o.Events),t.prototype.defaults={file:null,fileInfo:null,error:null,uploading:!1,deleting:!1},t.prototype.get=function(t){return this[t]},t.prototype.set=function(o){var e,r;this._previousAttributes=new t(this);for(e in o)r=o[e],this[e]=r;return this.trigger("change",this),this._previousAttributes=null},t.prototype.previousAttributes=function(){return this._previousAttributes},t.prototype.size=function(){var t;return null!=this._size?this._size:this._size=null!=(t=this.file)?t.size:void 0},t.prototype.lastModifiedDate=function(){var t;return null!=this._lastModifiedDate?this._lastModifiedDate:this._lastModifiedDate=null!=(t=this.file)?t.lastModifiedDate:void 0},t.prototype.updateWithProgress=function(t){var o;return o=new e(this.id,this.lastModifiedDate(),t.total,t.loaded),this.set({fileInfo:o})},t.prototype.getProgress=function(){return null==this.fileInfo||this.hasConflict()?null!=this.file?{loaded:0,total:this.size()}:void 0:{loaded:this.fileInfo.loaded,total:this.fileInfo.total}},t.prototype.isFullyUploaded=function(){return null!=this.fileInfo&&null==this.error&&!this.uploading&&!this.deleting&&this.fileInfo.loaded===this.fileInfo.total},t.prototype.hasConflict=function(){return null!=this.fileInfo&&null!=this.file&&(this.fileInfo.name!==this.id||this.fileInfo.total!==this.size()||this.fileInfo.lastModifiedDate.getTime()!==this.lastModifiedDate().getTime())},t}()}),define("MassUpload/UploadCollection",["backbone","./Upload"],function(t,o){var e,r;return r=function(){function t(){this._clear()}return t.prototype._clear=function(){return this.deleting=[],this.uploading=[],this.unfinished=[],this.unstarted=[]},t.prototype.uploadAttributesToState=function(t){var o;return o=null!=t.error?null:t.deleting?"deleting":t.uploading?"uploading":null!=t.file&&null!=t.fileInfo&&t.fileInfo.loadedr;r++)e=t[r],o=this.uploadAttributesToState(e.attributes),null!=o&&this[o].push(e);return void 0},t.prototype._removeUploadFromArray=function(t,o){var e;return e=o.indexOf(t),e>=0?o.splice(e,1):void 0},t.prototype.remove=function(t){var o;return o=this.uploadAttributesToState(t.attributes),null!=o?this._removeUploadFromArray(t.attributes,this[o]):void 0},t.prototype.change=function(t){var o,e;return e=this.uploadAttributesToState(t.previousAttributes()),o=this.uploadAttributesToState(t.attributes),e!==o&&(null!=e&&this._removeUploadFromArray(t,this[e]),null!=o)?this[o].push(t):void 0},t.prototype.reset=function(t){return null==t&&(t=[]),this._clear(),this.addBatch(t)},t.prototype.next=function(){var t,o,e,r;return null!=(t=null!=(o=null!=(e=null!=(r=this.deleting[0])?r:this.uploading[0])?e:this.unfinished[0])?o:this.unstarted[0])?t:null},t}(),e=function(){function e(){this.models=[],this._priorityQueue=new r,this.reset([])}return e.prototype=Object.create(t.Events),e.prototype.each=function(t,o){return this.models.forEach(t,o)},e.prototype.map=function(t,o){return this.models.map(t,o)},e.prototype._prepareModel=function(t){return t instanceof o?t:new o(t)},e.prototype.reset=function(t){var o,e,r,n,i,s,l;for(s=this.models,e=0,n=s.length;n>e;e++)o=s[e],o.off("all",this._onUploadEvent,this);for(this.models=function(){var e,r,n,i;for(n=null!=t?t:[],i=[],e=0,r=n.length;r>e;e++)o=n[e],i.push(this._prepareModel(o));return i}.call(this),this.length=this.models.length,this._idToModel={},l=this.models,r=0,i=l.length;i>r;r++)o=l[r],o.on("all",this._onUploadEvent,this),this._idToModel[o.id]=o;return this._priorityQueue.reset(this.models),this.trigger("reset",this)},e.prototype.get=function(t){var o;return null!=(o=this._idToModel[t])?o:null},e.prototype.forFile=function(t){return this.get(t.webkitRelativePath||t.name)},e.prototype.forFileInfo=function(t){return this.get(t.name)},e.prototype.addFiles=function(t){var e,r;return r=function(){var r,n,i;for(i=[],r=0,n=t.length;n>r;r++)e=t[r],i.push(new o({file:e}));return i}(),this._addWithMerge(r)},e.prototype.addFileInfos=function(t){var e,r;return r=function(){var r,n,i;for(i=[],r=0,n=t.length;n>r;r++)e=t[r],i.push(new o({fileInfo:e}));return i}(),this._addWithMerge(r)},e.prototype.next=function(){return this._priorityQueue.next()},e.prototype.add=function(t){return null!=t.length?this.addBatch(t):this.addBatch([t])},e.prototype.addBatch=function(t){var o,e,r,n,i;for(e=0,n=t.length;n>e;e++)o=t[e],this._idToModel[o.id]=o,o.on("all",this._onUploadEvent,this),this.models.push(o);for(this.length+=t.length,this._priorityQueue.addBatch(t),r=0,i=t.length;i>r;r++)o=t[r],this.trigger("add",o);return this.trigger("add-batch",t)},e.prototype._onUploadEvent=function(t,o){return"add"!==t&&"remove"!==t&&this.trigger.apply(this,arguments),"change"===t?this._priorityQueue.change(o):void 0},e.prototype._addWithMerge=function(t){var o,e,r,n,i,s,l;for(n=[],s=0,l=t.length;l>s;s++)i=t[s],null!=(o=this.get(i.id))?(e=i.get("file"),r=i.get("fileInfo"),null!=e&&o.set({file:e}),null!=r&&o.set({fileInfo:r})):n.push(i);return n.length&&this.add(n),void 0},e}()}),define("MassUpload/FileLister",[],function(){var t;return t=function(){function t(t,o){this.doListFiles=t,this.callbacks=o,this.running=!1}return t.prototype.run=function(){var t,o=this;if(this.running)throw"already running";return this.running=!0,"function"==typeof(t=this.callbacks).onStart&&t.onStart(),this.doListFiles(function(t){var e;return"function"==typeof(e=o.callbacks).onProgress?e.onProgress(t):void 0},function(t){return o._onSuccess(t)},function(t){return o._onError(t)})},t.prototype._onSuccess=function(t){var o;return"function"==typeof(o=this.callbacks).onSuccess&&o.onSuccess(t),this._onStop()},t.prototype._onError=function(t){return this.callbacks.onError(t),this._onStop()},t.prototype._onStop=function(){var t;return this.running=!1,"function"==typeof(t=this.callbacks).onStop?t.onStop():void 0},t}()}),define("MassUpload/FileUploader",["./FileInfo"],function(){var t;return t=function(){function t(t,o){this.doUpload=t,this.callbacks=o,this._file=null,this._abortCallback=null,this._aborting=!1}return t.prototype.run=function(t){var o,e=this;if(null!=this._file)throw"already running";return this._file=t,"function"==typeof(o=this.callbacks).onStart&&o.onStart(this._file),this._abortCallback=this.doUpload(t,function(o){return e._onProgress(t,o)},function(){return e._onSuccess(t)},function(o){return e._onError(t,o)})},t.prototype.abort=function(){return this._file&&!this._aborting&&(this._aborting=!0,"function"==typeof this._abortCallback)?this._abortCallback():void 0},t.prototype._onProgress=function(t,o){var e;return"function"==typeof(e=this.callbacks).onProgress?e.onProgress(t,o):void 0},t.prototype._onSuccess=function(t){var o;return"function"==typeof(o=this.callbacks).onSuccess&&o.onSuccess(t),this._onStop(t)},t.prototype._onError=function(t,o){var e;return"function"==typeof(e=this.callbacks).onError&&e.onError(t,o),this._onStop(t)},t.prototype._onStop=function(t){var o;return this._file=null,this._abortCallback=null,this._aborting=!1,"function"==typeof(o=this.callbacks).onStop?o.onStop(t):void 0},t}()}),define("MassUpload/FileDeleter",[],function(){var t;return t=function(){function t(t,o){this.doDeleteFile=t,this.callbacks=null!=o?o:{},this.running=!1}return t.prototype.run=function(t){var o,e=this;if(this.running)throw"already running";return this.running=!0,"function"==typeof(o=this.callbacks).onStart&&o.onStart(t),this.doDeleteFile(t,function(){return e._onSuccess(t)},function(o){return e._onError(t,o)})},t.prototype._onSuccess=function(t){var o;return"function"==typeof(o=this.callbacks).onSuccess&&o.onSuccess(t),this._onStop(t)},t.prototype._onError=function(t,o){var e;return"function"==typeof(e=this.callbacks).onError&&e.onError(t,o),this._onStop(t)},t.prototype._onStop=function(t){var o;return this.running=!1,"function"==typeof(o=this.callbacks).onStop&&o.onStop(t),void 0},t}()}),define("MassUpload/State",[],function(){var t;return t=function(){function t(t){var o,e,r,n;null==t&&(t={}),this.loaded=null!=(o=t.loaded)?o:0,this.total=null!=(e=t.total)?e:0,this.status=null!=(r=t.status)?r:"waiting",this.errors=null!=(n=t.errors)?n:[]}return t.prototype._extend=function(o){var e,r,n,i;return new t({loaded:null!=(e=o.loaded)?e:this.loaded,total:null!=(r=o.total)?r:this.total,status:null!=(n=o.status)?n:this.status,errors:null!=(i=o.errors)?i:this.errors})},t.prototype.isComplete=function(){return this.total&&this.loaded===this.total&&"waiting"===this.status&&!this.errors.length&&!0||!1},t.prototype.withTotal=function(t){return this._extend({total:t})},t.prototype.withLoaded=function(t){return this._extend({loaded:t})},t.prototype.withStatus=function(t){return this._extend({status:t})},t.prototype.withAnError=function(t){var o;return o=this.errors.slice(0),o.push(t),this._extend({errors:o})},t.prototype.withoutAnError=function(t){var o,e;return e=this.errors.slice(0),o=e.indexOf(t),e.splice(o,1),this._extend({errors:e})},t}()}),define("MassUpload/UploadProgress",["backbone"],function(t){return t.Model.extend({defaults:{loaded:0,total:0},initialize:function(){var t;if(t=this.get("uploadCollection"),null==t)throw"Must initialize UploadProgress with `uploadCollection`, an UploadCollection";return this._idToLastKnownProgress={},this._updateAndStartListening()},_adjust:function(t,o){return this.set({loaded:this.get("loaded")+t,total:this.get("total")+o})},add:function(t){var o;return o=t.getProgress(),this._adjust(o.loaded,o.total),this._idToLastKnownProgress[t.id]=o},reset:function(t){var o,e,r,n,i,s,l,u;for(o=this._idToLastKnownProgress={},e=0,i=0,u=t.models,s=0,l=u.length;l>s;s++)r=u[s],n=r.getProgress(),o[r.id]=n,e+=n.loaded,i+=n.total;return this.set({loaded:e,total:i})},remove:function(t){var o;return o=t.getProgress(),this._adjust(-o.loaded,-o.total),this._idToLastKnownProgress[t.id]=o},change:function(t){var o,e;return e=this._idToLastKnownProgress[t.id],null!=e?(o=t.getProgress(),this._adjust(o.loaded-e.loaded,o.total-e.total),this._idToLastKnownProgress[t.id]=o):void 0},_updateAndStartListening:function(){var t,o,e,r,n;for(t=this.get("uploadCollection"),n=["add","remove","change","reset"],e=0,r=n.length;r>e;e++)o=n[e],this.listenTo(t,o,this[o]);return this.reset(t),void 0},inBatch:function(t){this.stopListening(this.get("uploadCollection"));try{return t()}finally{this._updateAndStartListening()}}})});var __hasProp={}.hasOwnProperty,__extends=function(t,o){function e(){this.constructor=t}for(var r in o)__hasProp.call(o,r)&&(t[r]=o[r]);return e.prototype=o.prototype,t.prototype=new e,t.__super__=o.prototype,t};define("MassUpload",["backbone","underscore","MassUpload/UploadCollection","MassUpload/FileLister","MassUpload/FileUploader","MassUpload/FileDeleter","MassUpload/State","MassUpload/UploadProgress"],function(t,o,e,r,n,i,s,l){var u;return u=function(t){function s(t){this._removedUploads=[],s.__super__.constructor.call(this,{},t)}return __extends(s,t),s.prototype.defaults=function(){return{status:"waiting",listFilesProgress:null,listFilesError:null,uploadProgress:null,uploadErrors:[]}},s.prototype.initialize=function(t,o){var r,n,i=this;return this._options=o,this.uploads=null!=(n=null!=o?o.uploads:void 0)?n:new e,this._uploadProgress=new l({uploadCollection:this.uploads}),r=function(){return i.set({uploadProgress:i._uploadProgress.pick("loaded","total")})},this.listenTo(this._uploadProgress,"change",r),r(),this.listenTo(this.uploads,"add-batch",this._onUploadBatchAdded),this.listenTo(this.uploads,"change",function(t){return i._onUploadChanged(t)}),this.listenTo(this.uploads,"reset",function(){return i._onUploadsReset()}),this.prepare()},s.prototype.prepare=function(){var t,o,e,s,l=this;return t=this._options,this.lister=null!=(o=null!=t?t.lister:void 0)?o:new r(t.doListFiles),this.lister.callbacks={onStart:function(){return l._onListerStart()},onProgress:function(t){return l._onListerProgress(t)},onSuccess:function(t){return l._onListerSuccess(t)},onError:function(t){return l._onListerError(t)},onStop:function(){return l._onListerStop()}},this.uploader=null!=(e=null!=t?t.uploader:void 0)?e:new n(t.doUploadFile),this.uploader.callbacks={onStart:function(t){return l._onUploaderStart(t)},onStop:function(t){return l._onUploaderStop(t)},onSuccess:function(t){return l._onUploaderSuccess(t)},onError:function(t,o){return l._onUploaderError(t,o)},onProgress:function(t,o){return l._onUploaderProgress(t,o)}},this.deleter=null!=(s=null!=t?t.deleter:void 0)?s:new i(t.doDeleteFile),this.deleter.callbacks={onStart:function(t){return l._onDeleterStart(t)},onSuccess:function(t){return l._onDeleterSuccess(t)},onError:function(t,o){return l._onDeleterError(t,o)},onStop:function(t){return l._onDeleterStop(t)}}},s.prototype.fetchFileInfosFromServer=function(){return this.lister.run()},s.prototype.retryListFiles=function(){return this.fetchFileInfosFromServer()},s.prototype.retryUpload=function(t){return t.set({error:null})},s.prototype.retryAllUploads=function(){return this.uploads.each(function(t){return t.set({error:null})})},s.prototype.addFiles=function(t){var o=this;return this._uploadProgress.inBatch(function(){return o.uploads.addFiles(t)})},s.prototype.removeUpload=function(t){return t.set({deleting:!0})},s.prototype.abort=function(){var t=this;return this.uploads.each(function(o){return t.removeUpload(o)}),this.uploads.reset(),this.prepare()},s.prototype._onListerStart=function(){return this.set({status:"listing-files",listFilesError:null})},s.prototype._onListerProgress=function(t){return this.set({listFilesProgress:t})},s.prototype._onListerSuccess=function(t){return this.uploads.addFileInfos(t),this._tick()},s.prototype._onListerError=function(t){return this.set({listFilesError:t,status:"listing-files-error"})},s.prototype._onListerStop=function(){},s.prototype._mergeUploadError=function(t,e,r){var n,i;return i=this.get("uploadErrors").slice(0),n=o.sortedIndex(i,{upload:t},function(t){return t.upload.id}),null==e?i.splice(n,0,{upload:t,error:r}):null==r?i.splice(n,1):i[n].error=r,this.set({uploadErrors:i})},s.prototype._onUploadBatchAdded=function(t){var o,e,r,n;for(r=0,n=t.length;n>r;r++)e=t[r],o=e.get("error"),null!=o&&this._mergeUploadError(e,null,o);return this._forceBestTick()},s.prototype._onUploadChanged=function(t){var o,e,r,n;return r=t.previousAttributes().error,n=t.get("error"),r!==n&&this._mergeUploadError(t,r,n),o=t.previousAttributes().deleting,e=t.get("deleting"),e&&!o&&this._removedUploads.push(t),this._forceBestTick()},s.prototype._onUploadsReset=function(){var t;return t=[],this.uploads.each(function(o){var e;return(e=o.get("error"))?t.push({upload:o,error:e}):void 0}),this.set({uploadErrors:t}),this._tick()},s.prototype._onUploaderStart=function(t){var o;return o=this.uploads.forFile(t),o.set({uploading:!0,error:null})},s.prototype._onUploaderStop=function(t){var o;return o=this.uploads.forFile(t),o.set({uploading:!1}),this._tick()},s.prototype._onUploaderProgress=function(t,o){var e;return e=this.uploads.forFile(t),e.updateWithProgress(o)},s.prototype._onUploaderError=function(t,o){var e;return e=this.uploads.forFile(t),e.set({error:o})},s.prototype._onUploaderSuccess=function(t){var o;return o=this.uploads.forFile(t),o.updateWithProgress({loaded:o.size(),total:o.size()})},s.prototype._onDeleterStart=function(){return this.set({status:"uploading"})},s.prototype._onDeleterSuccess=function(t){var o;return o=this.uploads.forFileInfo(t),this.uploads.remove(o)},s.prototype._onDeleterError=function(t,o){var e;return e=this.uploads.forFileInfo(t),e.set({error:o})},s.prototype._onDeleterStop=function(){return this._tick()},s.prototype._tick=function(){var t,o,e;return e=this.uploads.next(),this._currentUpload=e,null!=e&&(e.get("deleting")?this.deleter.run(e.get("fileInfo")):this.uploader.run(e.get("file"))),o=this.get("uploadErrors").length?"uploading-error":null!=e?"uploading":(t=this.get("uploadProgress"),t.loaded===t.total?"waiting":"waiting-error"),this.set({status:o})},s.prototype._forceBestTick=function(){var t;return t=this.uploads.next(),t!==this._currentUpload?this._currentUpload?this.uploader.abort():this._tick():void 0},s}(t.Model)}),define("mass-upload",["MassUpload"],function(t){return t}); \ No newline at end of file diff --git a/dist/mass-upload.no-require.js b/dist/mass-upload.no-require.js deleted file mode 100644 index 7a3c075..0000000 --- a/dist/mass-upload.no-require.js +++ /dev/null @@ -1,1466 +0,0 @@ -(function () { -/** - * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/almond for details - */ -//Going sloppy to avoid 'use strict' string cost, but strict practices should -//be followed. -/*jslint sloppy: true */ -/*global setTimeout: false */ - -var requirejs, require, define; -(function (undef) { - var main, req, makeMap, handlers, - defined = {}, - waiting = {}, - config = {}, - defining = {}, - hasOwn = Object.prototype.hasOwnProperty, - aps = [].slice, - jsSuffixRegExp = /\.js$/; - - function hasProp(obj, prop) { - return hasOwn.call(obj, prop); - } - - /** - * Given a relative module name, like ./something, normalize it to - * a real name that can be mapped to a path. - * @param {String} name the relative name - * @param {String} baseName a real name that the name arg is relative - * to. - * @returns {String} normalized name - */ - function normalize(name, baseName) { - var nameParts, nameSegment, mapValue, foundMap, lastIndex, - foundI, foundStarMap, starI, i, j, part, - baseParts = baseName && baseName.split("/"), - map = config.map, - starMap = (map && map['*']) || {}; - - //Adjust any relative paths. - if (name && name.charAt(0) === ".") { - //If have a base name, try to normalize against it, - //otherwise, assume it is a top-level require that will - //be relative to baseUrl in the end. - if (baseName) { - //Convert baseName to array, and lop off the last part, - //so that . matches that "directory" and not name of the baseName's - //module. For instance, baseName of "one/two/three", maps to - //"one/two/three.js", but we want the directory, "one/two" for - //this normalization. - baseParts = baseParts.slice(0, baseParts.length - 1); - name = name.split('/'); - lastIndex = name.length - 1; - - // Node .js allowance: - if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { - name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); - } - - name = baseParts.concat(name); - - //start trimDots - for (i = 0; i < name.length; i += 1) { - part = name[i]; - if (part === ".") { - name.splice(i, 1); - i -= 1; - } else if (part === "..") { - if (i === 1 && (name[2] === '..' || name[0] === '..')) { - //End of the line. Keep at least one non-dot - //path segment at the front so it can be mapped - //correctly to disk. Otherwise, there is likely - //no path mapping for a path starting with '..'. - //This can still fail, but catches the most reasonable - //uses of .. - break; - } else if (i > 0) { - name.splice(i - 1, 2); - i -= 2; - } - } - } - //end trimDots - - name = name.join("/"); - } else if (name.indexOf('./') === 0) { - // No baseName, so this is ID is resolved relative - // to baseUrl, pull off the leading dot. - name = name.substring(2); - } - } - - //Apply map config if available. - if ((baseParts || starMap) && map) { - nameParts = name.split('/'); - - for (i = nameParts.length; i > 0; i -= 1) { - nameSegment = nameParts.slice(0, i).join("/"); - - if (baseParts) { - //Find the longest baseName segment match in the config. - //So, do joins on the biggest to smallest lengths of baseParts. - for (j = baseParts.length; j > 0; j -= 1) { - mapValue = map[baseParts.slice(0, j).join('/')]; - - //baseName segment has config, find if it has one for - //this name. - if (mapValue) { - mapValue = mapValue[nameSegment]; - if (mapValue) { - //Match, update name to the new value. - foundMap = mapValue; - foundI = i; - break; - } - } - } - } - - if (foundMap) { - break; - } - - //Check for a star map match, but just hold on to it, - //if there is a shorter segment match later in a matching - //config, then favor over this star map. - if (!foundStarMap && starMap && starMap[nameSegment]) { - foundStarMap = starMap[nameSegment]; - starI = i; - } - } - - if (!foundMap && foundStarMap) { - foundMap = foundStarMap; - foundI = starI; - } - - if (foundMap) { - nameParts.splice(0, foundI, foundMap); - name = nameParts.join('/'); - } - } - - return name; - } - - function makeRequire(relName, forceSync) { - return function () { - //A version of a require function that passes a moduleName - //value for items that may need to - //look up paths relative to the moduleName - return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync])); - }; - } - - function makeNormalize(relName) { - return function (name) { - return normalize(name, relName); - }; - } - - function makeLoad(depName) { - return function (value) { - defined[depName] = value; - }; - } - - function callDep(name) { - if (hasProp(waiting, name)) { - var args = waiting[name]; - delete waiting[name]; - defining[name] = true; - main.apply(undef, args); - } - - if (!hasProp(defined, name) && !hasProp(defining, name)) { - throw new Error('No ' + name); - } - return defined[name]; - } - - //Turns a plugin!resource to [plugin, resource] - //with the plugin being undefined if the name - //did not have a plugin prefix. - function splitPrefix(name) { - var prefix, - index = name ? name.indexOf('!') : -1; - if (index > -1) { - prefix = name.substring(0, index); - name = name.substring(index + 1, name.length); - } - return [prefix, name]; - } - - /** - * Makes a name map, normalizing the name, and using a plugin - * for normalization if necessary. Grabs a ref to plugin - * too, as an optimization. - */ - makeMap = function (name, relName) { - var plugin, - parts = splitPrefix(name), - prefix = parts[0]; - - name = parts[1]; - - if (prefix) { - prefix = normalize(prefix, relName); - plugin = callDep(prefix); - } - - //Normalize according - if (prefix) { - if (plugin && plugin.normalize) { - name = plugin.normalize(name, makeNormalize(relName)); - } else { - name = normalize(name, relName); - } - } else { - name = normalize(name, relName); - parts = splitPrefix(name); - prefix = parts[0]; - name = parts[1]; - if (prefix) { - plugin = callDep(prefix); - } - } - - //Using ridiculous property names for space reasons - return { - f: prefix ? prefix + '!' + name : name, //fullName - n: name, - pr: prefix, - p: plugin - }; - }; - - function makeConfig(name) { - return function () { - return (config && config.config && config.config[name]) || {}; - }; - } - - handlers = { - require: function (name) { - return makeRequire(name); - }, - exports: function (name) { - var e = defined[name]; - if (typeof e !== 'undefined') { - return e; - } else { - return (defined[name] = {}); - } - }, - module: function (name) { - return { - id: name, - uri: '', - exports: defined[name], - config: makeConfig(name) - }; - } - }; - - main = function (name, deps, callback, relName) { - var cjsModule, depName, ret, map, i, - args = [], - callbackType = typeof callback, - usingExports; - - //Use name if no relName - relName = relName || name; - - //Call the callback to define the module, if necessary. - if (callbackType === 'undefined' || callbackType === 'function') { - //Pull out the defined dependencies and pass the ordered - //values to the callback. - //Default to [require, exports, module] if no deps - deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; - for (i = 0; i < deps.length; i += 1) { - map = makeMap(deps[i], relName); - depName = map.f; - - //Fast path CommonJS standard dependencies. - if (depName === "require") { - args[i] = handlers.require(name); - } else if (depName === "exports") { - //CommonJS module spec 1.1 - args[i] = handlers.exports(name); - usingExports = true; - } else if (depName === "module") { - //CommonJS module spec 1.1 - cjsModule = args[i] = handlers.module(name); - } else if (hasProp(defined, depName) || - hasProp(waiting, depName) || - hasProp(defining, depName)) { - args[i] = callDep(depName); - } else if (map.p) { - map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); - args[i] = defined[depName]; - } else { - throw new Error(name + ' missing ' + depName); - } - } - - ret = callback ? callback.apply(defined[name], args) : undefined; - - if (name) { - //If setting exports via "module" is in play, - //favor that over return value and exports. After that, - //favor a non-undefined return value over exports use. - if (cjsModule && cjsModule.exports !== undef && - cjsModule.exports !== defined[name]) { - defined[name] = cjsModule.exports; - } else if (ret !== undef || !usingExports) { - //Use the return value from the function. - defined[name] = ret; - } - } - } else if (name) { - //May just be an object definition for the module. Only - //worry about defining if have a module name. - defined[name] = callback; - } - }; - - requirejs = require = req = function (deps, callback, relName, forceSync, alt) { - if (typeof deps === "string") { - if (handlers[deps]) { - //callback in this case is really relName - return handlers[deps](callback); - } - //Just return the module wanted. In this scenario, the - //deps arg is the module name, and second arg (if passed) - //is just the relName. - //Normalize module name, if it contains . or .. - return callDep(makeMap(deps, callback).f); - } else if (!deps.splice) { - //deps is a config object, not an array. - config = deps; - if (config.deps) { - req(config.deps, config.callback); - } - if (!callback) { - return; - } - - if (callback.splice) { - //callback is an array, which means it is a dependency list. - //Adjust args if there are dependencies - deps = callback; - callback = relName; - relName = null; - } else { - deps = undef; - } - } - - //Support require(['a']) - callback = callback || function () {}; - - //If relName is a function, it is an errback handler, - //so remove it. - if (typeof relName === 'function') { - relName = forceSync; - forceSync = alt; - } - - //Simulate async callback; - if (forceSync) { - main(undef, deps, callback, relName); - } else { - //Using a non-zero value because of concern for what old browsers - //do, and latest browsers "upgrade" to 4 if lower value is used: - //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: - //If want a value immediately, use require('id') instead -- something - //that works in almond on the global level, but not guaranteed and - //unlikely to work in other AMD implementations. - setTimeout(function () { - main(undef, deps, callback, relName); - }, 4); - } - - return req; - }; - - /** - * Just drops the config on the floor, but returns req in case - * the config return value is used. - */ - req.config = function (cfg) { - return req(cfg); - }; - - /** - * Expose module registry for debugging and tooling - */ - requirejs._defined = defined; - - define = function (name, deps, callback) { - - //This module may not have dependencies - if (!deps.splice) { - //deps is not an array, so probably means - //an object literal or factory function for - //the value. Adjust args. - callback = deps; - deps = []; - } - - if (!hasProp(defined, name) && !hasProp(waiting, name)) { - waiting[name] = [name, deps, callback]; - } - }; - - define.amd = { - jQuery: true - }; -}()); - -define("almond", function(){}); - -define('MassUpload/FileInfo',[],function() { - var FileInfo; - FileInfo = (function() { - function FileInfo(name, lastModifiedDate, total, loaded) { - this.name = name; - this.lastModifiedDate = lastModifiedDate; - this.total = total; - this.loaded = loaded; - } - - return FileInfo; - - })(); - FileInfo.fromJson = function(obj) { - return new FileInfo(obj.name, new Date(obj.lastModifiedDate), obj.total, obj.loaded); - }; - FileInfo.fromFile = function(obj) { - return new FileInfo(obj.webkitRelativePath || obj.name, obj.lastModifiedDate, obj.size, 0); - }; - return FileInfo; -}); - -define('MassUpload/Upload',['underscore', 'backbone', './FileInfo'], function(_, Backbone, FileInfo) { - var Upload; - return Upload = (function() { - Upload.prototype = Object.create(Backbone.Events); - - Upload.prototype.defaults = { - file: null, - fileInfo: null, - error: null, - uploading: false, - deleting: false - }; - - function Upload(attributes) { - var _ref, _ref1, _ref2; - this.file = (_ref = attributes.file) != null ? _ref : null; - this.fileInfo = (_ref1 = attributes.fileInfo) != null ? _ref1 : null; - this.error = (_ref2 = attributes.error) != null ? _ref2 : null; - this.uploading = attributes.uploading || false; - this.deleting = attributes.deleting || false; - this.id = this.file != null ? this.file.webkitRelativePath || this.file.name : this.fileInfo.name; - this.attributes = this; - } - - Upload.prototype.get = function(attr) { - return this[attr]; - }; - - Upload.prototype.set = function(attrs) { - var k, v; - this._previousAttributes = new Upload(this); - for (k in attrs) { - v = attrs[k]; - this[k] = v; - } - this.trigger('change', this); - return this._previousAttributes = null; - }; - - Upload.prototype.previousAttributes = function() { - return this._previousAttributes; - }; - - Upload.prototype.size = function() { - var _ref; - return this._size != null ? this._size : this._size = (_ref = this.file) != null ? _ref.size : void 0; - }; - - Upload.prototype.lastModifiedDate = function() { - var _ref; - return this._lastModifiedDate != null ? this._lastModifiedDate : this._lastModifiedDate = (_ref = this.file) != null ? _ref.lastModifiedDate : void 0; - }; - - Upload.prototype.updateWithProgress = function(progressEvent) { - var fileInfo; - fileInfo = new FileInfo(this.id, this.lastModifiedDate(), progressEvent.total, progressEvent.loaded); - return this.set({ - fileInfo: fileInfo - }); - }; - - Upload.prototype.getProgress = function() { - if ((this.fileInfo != null) && !this.hasConflict()) { - return { - loaded: this.fileInfo.loaded, - total: this.fileInfo.total - }; - } else if (this.file != null) { - return { - loaded: 0, - total: this.size() - }; - } - }; - - Upload.prototype.isFullyUploaded = function() { - return (this.fileInfo != null) && (this.error == null) && !this.uploading && !this.deleting && this.fileInfo.loaded === this.fileInfo.total; - }; - - Upload.prototype.hasConflict = function() { - return (this.fileInfo != null) && (this.file != null) && (this.fileInfo.name !== this.id || this.fileInfo.total !== this.size() || this.fileInfo.lastModifiedDate.getTime() !== this.lastModifiedDate().getTime()); - }; - - return Upload; - - })(); -}); - -define('MassUpload/UploadCollection',['backbone', './Upload'], function(Backbone, Upload) { - var UploadCollection, UploadPriorityQueue; - UploadPriorityQueue = (function() { - function UploadPriorityQueue() { - this._clear(); - } - - UploadPriorityQueue.prototype._clear = function() { - this.deleting = []; - this.uploading = []; - this.unfinished = []; - return this.unstarted = []; - }; - - UploadPriorityQueue.prototype.uploadAttributesToState = function(uploadAttributes) { - var ret; - ret = uploadAttributes.error != null ? null : uploadAttributes.deleting ? 'deleting' : uploadAttributes.uploading ? 'uploading' : (uploadAttributes.file != null) && (uploadAttributes.fileInfo != null) && uploadAttributes.fileInfo.loaded < uploadAttributes.fileInfo.total ? 'unfinished' : (uploadAttributes.file != null) && (uploadAttributes.fileInfo == null) ? 'unstarted' : null; - return ret; - }; - - UploadPriorityQueue.prototype.addBatch = function(uploads) { - var state, upload, _i, _len; - for (_i = 0, _len = uploads.length; _i < _len; _i++) { - upload = uploads[_i]; - state = this.uploadAttributesToState(upload.attributes); - if (state != null) { - this[state].push(upload); - } - } - return void 0; - }; - - UploadPriorityQueue.prototype._removeUploadFromArray = function(upload, array) { - var idx; - idx = array.indexOf(upload); - if (idx >= 0) { - return array.splice(idx, 1); - } - }; - - UploadPriorityQueue.prototype.remove = function(upload) { - var state; - state = this.uploadAttributesToState(upload.attributes); - if (state != null) { - return this._removeUploadFromArray(upload.attributes, this[state]); - } - }; - - UploadPriorityQueue.prototype.change = function(upload) { - var newState, prevState; - prevState = this.uploadAttributesToState(upload.previousAttributes()); - newState = this.uploadAttributesToState(upload.attributes); - if (prevState !== newState) { - if (prevState != null) { - this._removeUploadFromArray(upload, this[prevState]); - } - if (newState != null) { - return this[newState].push(upload); - } - } - }; - - UploadPriorityQueue.prototype.reset = function(uploads) { - if (uploads == null) { - uploads = []; - } - this._clear(); - return this.addBatch(uploads); - }; - - UploadPriorityQueue.prototype.next = function() { - var _ref, _ref1, _ref2, _ref3; - return (_ref = (_ref1 = (_ref2 = (_ref3 = this.deleting[0]) != null ? _ref3 : this.uploading[0]) != null ? _ref2 : this.unfinished[0]) != null ? _ref1 : this.unstarted[0]) != null ? _ref : null; - }; - - return UploadPriorityQueue; - - })(); - return UploadCollection = (function() { - UploadCollection.prototype = Object.create(Backbone.Events); - - function UploadCollection() { - this.models = []; - this._priorityQueue = new UploadPriorityQueue(); - this.reset([]); - } - - UploadCollection.prototype.each = function(func, context) { - return this.models.forEach(func, context); - }; - - UploadCollection.prototype.map = function(func, context) { - return this.models.map(func, context); - }; - - UploadCollection.prototype._prepareModel = function(upload) { - if (upload instanceof Upload) { - return upload; - } else { - return new Upload(upload); - } - }; - - UploadCollection.prototype.reset = function(uploads) { - var upload, _i, _j, _len, _len1, _ref, _ref1; - _ref = this.models; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - upload = _ref[_i]; - upload.off('all', this._onUploadEvent, this); - } - this.models = (function() { - var _j, _len1, _ref1, _results; - _ref1 = uploads != null ? uploads : []; - _results = []; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - upload = _ref1[_j]; - _results.push(this._prepareModel(upload)); - } - return _results; - }).call(this); - this.length = this.models.length; - this._idToModel = {}; - _ref1 = this.models; - for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { - upload = _ref1[_j]; - upload.on('all', this._onUploadEvent, this); - this._idToModel[upload.id] = upload; - } - this._priorityQueue.reset(this.models); - return this.trigger('reset', this); - }; - - UploadCollection.prototype.get = function(id) { - var _ref; - return (_ref = this._idToModel[id]) != null ? _ref : null; - }; - - UploadCollection.prototype.forFile = function(file) { - return this.get(file.webkitRelativePath || file.name); - }; - - UploadCollection.prototype.forFileInfo = function(fileInfo) { - return this.get(fileInfo.name); - }; - - UploadCollection.prototype.addFiles = function(files) { - var file, uploads; - uploads = (function() { - var _i, _len, _results; - _results = []; - for (_i = 0, _len = files.length; _i < _len; _i++) { - file = files[_i]; - _results.push(new Upload({ - file: file - })); - } - return _results; - })(); - return this._addWithMerge(uploads); - }; - - UploadCollection.prototype.addFileInfos = function(fileInfos) { - var fileInfo, uploads; - uploads = (function() { - var _i, _len, _results; - _results = []; - for (_i = 0, _len = fileInfos.length; _i < _len; _i++) { - fileInfo = fileInfos[_i]; - _results.push(new Upload({ - fileInfo: fileInfo - })); - } - return _results; - })(); - return this._addWithMerge(uploads); - }; - - UploadCollection.prototype.next = function() { - return this._priorityQueue.next(); - }; - - UploadCollection.prototype.add = function(uploadOrUploads) { - if (uploadOrUploads.length != null) { - return this.addBatch(uploadOrUploads); - } else { - return this.addBatch([uploadOrUploads]); - } - }; - - UploadCollection.prototype.addBatch = function(uploads) { - var upload, _i, _j, _len, _len1; - for (_i = 0, _len = uploads.length; _i < _len; _i++) { - upload = uploads[_i]; - this._idToModel[upload.id] = upload; - upload.on('all', this._onUploadEvent, this); - this.models.push(upload); - } - this.length += uploads.length; - this._priorityQueue.addBatch(uploads); - for (_j = 0, _len1 = uploads.length; _j < _len1; _j++) { - upload = uploads[_j]; - this.trigger('add', upload); - } - return this.trigger('add-batch', uploads); - }; - - UploadCollection.prototype._onUploadEvent = function(event, model, collection, options) { - if (event !== 'add' && event !== 'remove') { - this.trigger.apply(this, arguments); - } - if (event === 'change') { - return this._priorityQueue.change(model); - } - }; - - UploadCollection.prototype._addWithMerge = function(uploads) { - var existingUpload, file, fileInfo, toAdd, upload, _i, _len; - toAdd = []; - for (_i = 0, _len = uploads.length; _i < _len; _i++) { - upload = uploads[_i]; - if ((existingUpload = this.get(upload.id)) != null) { - file = upload.get('file'); - fileInfo = upload.get('fileInfo'); - if (file != null) { - existingUpload.set({ - file: file - }); - } - if (fileInfo != null) { - existingUpload.set({ - fileInfo: fileInfo - }); - } - } else { - toAdd.push(upload); - } - } - if (toAdd.length) { - this.add(toAdd); - } - return void 0; - }; - - return UploadCollection; - - })(); -}); - -define('MassUpload/FileLister',[],function() { - var FileLister; - return FileLister = (function() { - function FileLister(doListFiles, callbacks) { - this.doListFiles = doListFiles; - this.callbacks = callbacks; - this.running = false; - } - - FileLister.prototype.run = function() { - var _base, - _this = this; - if (this.running) { - throw 'already running'; - } - this.running = true; - if (typeof (_base = this.callbacks).onStart === "function") { - _base.onStart(); - } - return this.doListFiles((function(progressEvent) { - var _base1; - return typeof (_base1 = _this.callbacks).onProgress === "function" ? _base1.onProgress(progressEvent) : void 0; - }), (function(fileInfos) { - return _this._onSuccess(fileInfos); - }), (function(errorDetail) { - return _this._onError(errorDetail); - })); - }; - - FileLister.prototype._onSuccess = function(fileInfos) { - var _base; - if (typeof (_base = this.callbacks).onSuccess === "function") { - _base.onSuccess(fileInfos); - } - return this._onStop(); - }; - - FileLister.prototype._onError = function(errorDetail) { - this.callbacks.onError(errorDetail); - return this._onStop(); - }; - - FileLister.prototype._onStop = function() { - var _base; - this.running = false; - return typeof (_base = this.callbacks).onStop === "function" ? _base.onStop() : void 0; - }; - - return FileLister; - - })(); -}); - -define('MassUpload/FileUploader',['./FileInfo'], function(FileInfo) { - var FileUploader; - return FileUploader = (function() { - function FileUploader(doUpload, callbacks) { - this.doUpload = doUpload; - this.callbacks = callbacks; - this._file = null; - this._abortCallback = null; - this._aborting = false; - } - - FileUploader.prototype.run = function(file) { - var _base, - _this = this; - if (this._file != null) { - throw 'already running'; - } - this._file = file; - if (typeof (_base = this.callbacks).onStart === "function") { - _base.onStart(this._file); - } - return this._abortCallback = this.doUpload(file, (function(progressEvent) { - return _this._onProgress(file, progressEvent); - }), (function() { - return _this._onSuccess(file); - }), (function(errorDetail) { - return _this._onError(file, errorDetail); - })); - }; - - FileUploader.prototype.abort = function() { - if (this._file && !this._aborting) { - this._aborting = true; - if (typeof this._abortCallback === 'function') { - return this._abortCallback(); - } - } - }; - - FileUploader.prototype._onProgress = function(file, progressEvent) { - var _base; - return typeof (_base = this.callbacks).onProgress === "function" ? _base.onProgress(file, progressEvent) : void 0; - }; - - FileUploader.prototype._onSuccess = function(file) { - var _base; - if (typeof (_base = this.callbacks).onSuccess === "function") { - _base.onSuccess(file); - } - return this._onStop(file); - }; - - FileUploader.prototype._onError = function(file, errorDetail) { - var _base; - if (typeof (_base = this.callbacks).onError === "function") { - _base.onError(file, errorDetail); - } - return this._onStop(file); - }; - - FileUploader.prototype._onStop = function(file) { - var _base; - this._file = null; - this._abortCallback = null; - this._aborting = false; - return typeof (_base = this.callbacks).onStop === "function" ? _base.onStop(file) : void 0; - }; - - return FileUploader; - - })(); -}); - -define('MassUpload/FileDeleter',[],function() { - var FileDeleter; - return FileDeleter = (function() { - function FileDeleter(doDeleteFile, callbacks) { - this.doDeleteFile = doDeleteFile; - this.callbacks = callbacks != null ? callbacks : {}; - this.running = false; - } - - FileDeleter.prototype.run = function(fileInfo) { - var _base, - _this = this; - if (this.running) { - throw 'already running'; - } - this.running = true; - if (typeof (_base = this.callbacks).onStart === "function") { - _base.onStart(fileInfo); - } - return this.doDeleteFile(fileInfo, (function() { - return _this._onSuccess(fileInfo); - }), (function(errorDetail) { - return _this._onError(fileInfo, errorDetail); - })); - }; - - FileDeleter.prototype._onSuccess = function(fileInfo) { - var _base; - if (typeof (_base = this.callbacks).onSuccess === "function") { - _base.onSuccess(fileInfo); - } - return this._onStop(fileInfo); - }; - - FileDeleter.prototype._onError = function(fileInfo, errorDetail) { - var _base; - if (typeof (_base = this.callbacks).onError === "function") { - _base.onError(fileInfo, errorDetail); - } - return this._onStop(fileInfo); - }; - - FileDeleter.prototype._onStop = function(fileInfo) { - var _base; - this.running = false; - if (typeof (_base = this.callbacks).onStop === "function") { - _base.onStop(fileInfo); - } - return void 0; - }; - - return FileDeleter; - - })(); -}); - -define('MassUpload/State',[],function() { - var State; - return State = (function() { - function State(attrs) { - var _ref, _ref1, _ref2, _ref3; - if (attrs == null) { - attrs = {}; - } - this.loaded = (_ref = attrs.loaded) != null ? _ref : 0; - this.total = (_ref1 = attrs.total) != null ? _ref1 : 0; - this.status = (_ref2 = attrs.status) != null ? _ref2 : 'waiting'; - this.errors = (_ref3 = attrs.errors) != null ? _ref3 : []; - } - - State.prototype._extend = function(attrs) { - var _ref, _ref1, _ref2, _ref3; - return new State({ - loaded: (_ref = attrs.loaded) != null ? _ref : this.loaded, - total: (_ref1 = attrs.total) != null ? _ref1 : this.total, - status: (_ref2 = attrs.status) != null ? _ref2 : this.status, - errors: (_ref3 = attrs.errors) != null ? _ref3 : this.errors - }); - }; - - State.prototype.isComplete = function() { - return this.total && this.loaded === this.total && this.status === 'waiting' && !this.errors.length && true || false; - }; - - State.prototype.withTotal = function(total) { - return this._extend({ - total: total - }); - }; - - State.prototype.withLoaded = function(loaded) { - return this._extend({ - loaded: loaded - }); - }; - - State.prototype.withStatus = function(status) { - return this._extend({ - status: status - }); - }; - - State.prototype.withAnError = function(error) { - var newErrors; - newErrors = this.errors.slice(0); - newErrors.push(error); - return this._extend({ - errors: newErrors - }); - }; - - State.prototype.withoutAnError = function(error) { - var index, newErrors; - newErrors = this.errors.slice(0); - index = newErrors.indexOf(error); - newErrors.splice(index, 1); - return this._extend({ - errors: newErrors - }); - }; - - return State; - - })(); -}); - -define('MassUpload/UploadProgress',['backbone'], function(Backbone) { - return Backbone.Model.extend({ - defaults: { - loaded: 0, - total: 0 - }, - initialize: function() { - var collection; - collection = this.get('uploadCollection'); - if (collection == null) { - throw 'Must initialize UploadProgress with `uploadCollection`, an UploadCollection'; - } - this._idToLastKnownProgress = {}; - return this._updateAndStartListening(); - }, - _adjust: function(dLoaded, dTotal) { - return this.set({ - loaded: this.get('loaded') + dLoaded, - total: this.get('total') + dTotal - }); - }, - add: function(model) { - var progress; - progress = model.getProgress(); - this._adjust(progress.loaded, progress.total); - return this._idToLastKnownProgress[model.id] = progress; - }, - reset: function(collection) { - var idToLastKnownProgress, loaded, model, progress, total, _i, _len, _ref; - idToLastKnownProgress = this._idToLastKnownProgress = {}; - loaded = 0; - total = 0; - _ref = collection.models; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - model = _ref[_i]; - progress = model.getProgress(); - idToLastKnownProgress[model.id] = progress; - loaded += progress.loaded; - total += progress.total; - } - return this.set({ - loaded: loaded, - total: total - }); - }, - remove: function(model) { - var progress; - progress = model.getProgress(); - this._adjust(-progress.loaded, -progress.total); - return this._idToLastKnownProgress[model.id] = progress; - }, - change: function(model) { - var newProgress, oldProgress; - oldProgress = this._idToLastKnownProgress[model.id]; - if (oldProgress != null) { - newProgress = model.getProgress(); - this._adjust(newProgress.loaded - oldProgress.loaded, newProgress.total - oldProgress.total); - return this._idToLastKnownProgress[model.id] = newProgress; - } - }, - _updateAndStartListening: function() { - var collection, event, _i, _len, _ref; - collection = this.get('uploadCollection'); - _ref = ['add', 'remove', 'change', 'reset']; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - event = _ref[_i]; - this.listenTo(collection, event, this[event]); - } - this.reset(collection); - return void 0; - }, - inBatch: function(callback) { - this.stopListening(this.get('uploadCollection')); - try { - return callback(); - } finally { - this._updateAndStartListening(); - } - } - }); -}); - -var __hasProp = {}.hasOwnProperty, - __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }; - -define('MassUpload',['backbone', 'underscore', 'MassUpload/UploadCollection', 'MassUpload/FileLister', 'MassUpload/FileUploader', 'MassUpload/FileDeleter', 'MassUpload/State', 'MassUpload/UploadProgress'], function(Backbone, _, UploadCollection, FileLister, FileUploader, FileDeleter, State, UploadProgress) { - var MassUpload; - return MassUpload = (function(_super) { - __extends(MassUpload, _super); - - MassUpload.prototype.defaults = function() { - return { - status: 'waiting', - listFilesProgress: null, - listFilesError: null, - uploadProgress: null, - uploadErrors: [] - }; - }; - - function MassUpload(options) { - this._removedUploads = []; - MassUpload.__super__.constructor.call(this, {}, options); - } - - MassUpload.prototype.initialize = function(attributes, options) { - var resetUploadProgress, _ref, - _this = this; - this._options = options; - this.uploads = (_ref = options != null ? options.uploads : void 0) != null ? _ref : new UploadCollection(); - this._uploadProgress = new UploadProgress({ - uploadCollection: this.uploads - }); - resetUploadProgress = function() { - return _this.set({ - uploadProgress: _this._uploadProgress.pick('loaded', 'total') - }); - }; - this.listenTo(this._uploadProgress, 'change', resetUploadProgress); - resetUploadProgress(); - this.listenTo(this.uploads, 'add-batch', this._onUploadBatchAdded); - this.listenTo(this.uploads, 'change', function(upload) { - return _this._onUploadChanged(upload); - }); - this.listenTo(this.uploads, 'reset', function() { - return _this._onUploadsReset(); - }); - return this.prepare(); - }; - - MassUpload.prototype.prepare = function() { - var options, _ref, _ref1, _ref2, - _this = this; - options = this._options; - this.lister = (_ref = options != null ? options.lister : void 0) != null ? _ref : new FileLister(options.doListFiles); - this.lister.callbacks = { - onStart: function() { - return _this._onListerStart(); - }, - onProgress: function(progressEvent) { - return _this._onListerProgress(progressEvent); - }, - onSuccess: function(fileInfos) { - return _this._onListerSuccess(fileInfos); - }, - onError: function(errorDetail) { - return _this._onListerError(errorDetail); - }, - onStop: function() { - return _this._onListerStop(); - } - }; - this.uploader = (_ref1 = options != null ? options.uploader : void 0) != null ? _ref1 : new FileUploader(options.doUploadFile); - this.uploader.callbacks = { - onStart: function(file) { - return _this._onUploaderStart(file); - }, - onStop: function(file) { - return _this._onUploaderStop(file); - }, - onSuccess: function(file) { - return _this._onUploaderSuccess(file); - }, - onError: function(file, errorDetail) { - return _this._onUploaderError(file, errorDetail); - }, - onProgress: function(file, progressEvent) { - return _this._onUploaderProgress(file, progressEvent); - } - }; - this.deleter = (_ref2 = options != null ? options.deleter : void 0) != null ? _ref2 : new FileDeleter(options.doDeleteFile); - return this.deleter.callbacks = { - onStart: function(fileInfo) { - return _this._onDeleterStart(fileInfo); - }, - onSuccess: function(fileInfo) { - return _this._onDeleterSuccess(fileInfo); - }, - onError: function(fileInfo, errorDetail) { - return _this._onDeleterError(fileInfo, errorDetail); - }, - onStop: function(fileInfo) { - return _this._onDeleterStop(fileInfo); - } - }; - }; - - MassUpload.prototype.fetchFileInfosFromServer = function() { - return this.lister.run(); - }; - - MassUpload.prototype.retryListFiles = function() { - return this.fetchFileInfosFromServer(); - }; - - MassUpload.prototype.retryUpload = function(upload) { - return upload.set({ - error: null - }); - }; - - MassUpload.prototype.retryAllUploads = function() { - return this.uploads.each(function(upload) { - return upload.set({ - error: null - }); - }); - }; - - MassUpload.prototype.addFiles = function(files) { - var _this = this; - return this._uploadProgress.inBatch(function() { - return _this.uploads.addFiles(files); - }); - }; - - MassUpload.prototype.removeUpload = function(upload) { - return upload.set({ - deleting: true - }); - }; - - MassUpload.prototype.abort = function() { - var _this = this; - this.uploads.each(function(upload) { - return _this.removeUpload(upload); - }); - this.uploads.reset(); - return this.prepare(); - }; - - MassUpload.prototype._onListerStart = function() { - return this.set({ - status: 'listing-files', - listFilesError: null - }); - }; - - MassUpload.prototype._onListerProgress = function(progressEvent) { - return this.set({ - listFilesProgress: progressEvent - }); - }; - - MassUpload.prototype._onListerSuccess = function(fileInfos) { - this.uploads.addFileInfos(fileInfos); - return this._tick(); - }; - - MassUpload.prototype._onListerError = function(errorDetail) { - return this.set({ - listFilesError: errorDetail, - status: 'listing-files-error' - }); - }; - - MassUpload.prototype._onListerStop = function() {}; - - MassUpload.prototype._mergeUploadError = function(upload, prevError, curError) { - var index, newErrors; - newErrors = this.get('uploadErrors').slice(0); - index = _.sortedIndex(newErrors, { - upload: upload - }, function(x) { - return x.upload.id; - }); - if (prevError == null) { - newErrors.splice(index, 0, { - upload: upload, - error: curError - }); - } else if (curError == null) { - newErrors.splice(index, 1); - } else { - newErrors[index].error = curError; - } - return this.set({ - uploadErrors: newErrors - }); - }; - - MassUpload.prototype._onUploadBatchAdded = function(uploads) { - var error, upload, _i, _len; - for (_i = 0, _len = uploads.length; _i < _len; _i++) { - upload = uploads[_i]; - error = upload.get('error'); - if (error != null) { - this._mergeUploadError(upload, null, error); - } - } - return this._forceBestTick(); - }; - - MassUpload.prototype._onUploadChanged = function(upload) { - var deleting1, deleting2, error1, error2; - error1 = upload.previousAttributes().error; - error2 = upload.get('error'); - if (error1 !== error2) { - this._mergeUploadError(upload, error1, error2); - } - deleting1 = upload.previousAttributes().deleting; - deleting2 = upload.get('deleting'); - if (deleting2 && !deleting1) { - this._removedUploads.push(upload); - } - return this._forceBestTick(); - }; - - MassUpload.prototype._onUploadsReset = function() { - var newErrors; - newErrors = []; - this.uploads.each(function(upload) { - var error; - if ((error = upload.get('error'))) { - return newErrors.push({ - upload: upload, - error: error - }); - } - }); - this.set({ - uploadErrors: newErrors - }); - return this._tick(); - }; - - MassUpload.prototype._onUploaderStart = function(file) { - var upload; - upload = this.uploads.forFile(file); - return upload.set({ - uploading: true, - error: null - }); - }; - - MassUpload.prototype._onUploaderStop = function(file) { - var upload; - upload = this.uploads.forFile(file); - upload.set({ - uploading: false - }); - return this._tick(); - }; - - MassUpload.prototype._onUploaderProgress = function(file, progressEvent) { - var upload; - upload = this.uploads.forFile(file); - return upload.updateWithProgress(progressEvent); - }; - - MassUpload.prototype._onUploaderError = function(file, errorDetail) { - var upload; - upload = this.uploads.forFile(file); - return upload.set({ - error: errorDetail - }); - }; - - MassUpload.prototype._onUploaderSuccess = function(file) { - var upload; - upload = this.uploads.forFile(file); - return upload.updateWithProgress({ - loaded: upload.size(), - total: upload.size() - }); - }; - - MassUpload.prototype._onDeleterStart = function(fileInfo) { - return this.set({ - status: 'uploading' - }); - }; - - MassUpload.prototype._onDeleterSuccess = function(fileInfo) { - var upload; - upload = this.uploads.forFileInfo(fileInfo); - return this.uploads.remove(upload); - }; - - MassUpload.prototype._onDeleterError = function(fileInfo, errorDetail) { - var upload; - upload = this.uploads.forFileInfo(fileInfo); - return upload.set({ - error: errorDetail - }); - }; - - MassUpload.prototype._onDeleterStop = function(fileInfo) { - return this._tick(); - }; - - MassUpload.prototype._tick = function() { - var progress, status, upload; - upload = this.uploads.next(); - this._currentUpload = upload; - if (upload != null) { - if (upload.get('deleting')) { - this.deleter.run(upload.get('fileInfo')); - } else { - this.uploader.run(upload.get('file')); - } - } - status = this.get('uploadErrors').length ? 'uploading-error' : upload != null ? 'uploading' : (progress = this.get('uploadProgress'), progress.loaded === progress.total ? 'waiting' : 'waiting-error'); - return this.set({ - status: status - }); - }; - - MassUpload.prototype._forceBestTick = function() { - var upload; - upload = this.uploads.next(); - if (upload !== this._currentUpload) { - if (this._currentUpload) { - return this.uploader.abort(); - } else { - return this._tick(); - } - } - }; - - return MassUpload; - - })(Backbone.Model); -}); - -require(['./MassUpload'], function(MassUpload) { - return window.MassUpload = MassUpload; -}); - -define("index", function(){}); -}()); \ No newline at end of file diff --git a/dist/mass-upload.no-require.min.js b/dist/mass-upload.no-require.min.js deleted file mode 100644 index e0751bf..0000000 --- a/dist/mass-upload.no-require.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/jrburke/almond for details - */ - -!function(){var t,o,e;!function(r){function n(t,o){return S.call(t,o)}function i(t,o){var e,r,n,i,s,l,u,a,p,d,f,c=o&&o.split("/"),h=y.map,g=h&&h["*"]||{};if(t&&"."===t.charAt(0))if(o){for(c=c.slice(0,c.length-1),t=t.split("/"),s=t.length-1,y.nodeIdCompat&&m.test(t[s])&&(t[s]=t[s].replace(m,"")),t=c.concat(t),p=0;p0&&(t.splice(p-1,2),p-=2)}t=t.join("/")}else 0===t.indexOf("./")&&(t=t.substring(2));if((c||g)&&h){for(e=t.split("/"),p=e.length;p>0;p-=1){if(r=e.slice(0,p).join("/"),c)for(d=c.length;d>0;d-=1)if(n=h[c.slice(0,d).join("/")],n&&(n=n[r])){i=n,l=p;break}if(i)break;!u&&g&&g[r]&&(u=g[r],a=p)}!i&&u&&(i=u,l=a),i&&(e.splice(0,l,i),t=e.join("/"))}return t}function s(t,o){return function(){return c.apply(r,U.call(arguments,0).concat([t,o]))}}function l(t){return function(o){return i(o,t)}}function u(t){return function(o){_[t]=o}}function a(t){if(n(v,t)){var o=v[t];delete v[t],b[t]=!0,f.apply(r,o)}if(!n(_,t)&&!n(b,t))throw new Error("No "+t);return _[t]}function p(t){var o,e=t?t.indexOf("!"):-1;return e>-1&&(o=t.substring(0,e),t=t.substring(e+1,t.length)),[o,t]}function d(t){return function(){return y&&y.config&&y.config[t]||{}}}var f,c,h,g,_={},v={},y={},b={},S=Object.prototype.hasOwnProperty,U=[].slice,m=/\.js$/;h=function(t,o){var e,r=p(t),n=r[0];return t=r[1],n&&(n=i(n,o),e=a(n)),n?t=e&&e.normalize?e.normalize(t,l(o)):i(t,o):(t=i(t,o),r=p(t),n=r[0],t=r[1],n&&(e=a(n))),{f:n?n+"!"+t:t,n:t,pr:n,p:e}},g={require:function(t){return s(t)},exports:function(t){var o=_[t];return"undefined"!=typeof o?o:_[t]={}},module:function(t){return{id:t,uri:"",exports:_[t],config:d(t)}}},f=function(t,o,e,i){var l,p,d,f,c,y,S=[],U=typeof e;if(i=i||t,"undefined"===U||"function"===U){for(o=!o.length&&e.length?["require","exports","module"]:o,c=0;cr;r++)e=t[r],o=this.uploadAttributesToState(e.attributes),null!=o&&this[o].push(e);return void 0},t.prototype._removeUploadFromArray=function(t,o){var e;return e=o.indexOf(t),e>=0?o.splice(e,1):void 0},t.prototype.remove=function(t){var o;return o=this.uploadAttributesToState(t.attributes),null!=o?this._removeUploadFromArray(t.attributes,this[o]):void 0},t.prototype.change=function(t){var o,e;return e=this.uploadAttributesToState(t.previousAttributes()),o=this.uploadAttributesToState(t.attributes),e!==o&&(null!=e&&this._removeUploadFromArray(t,this[e]),null!=o)?this[o].push(t):void 0},t.prototype.reset=function(t){return null==t&&(t=[]),this._clear(),this.addBatch(t)},t.prototype.next=function(){var t,o,e,r;return null!=(t=null!=(o=null!=(e=null!=(r=this.deleting[0])?r:this.uploading[0])?e:this.unfinished[0])?o:this.unstarted[0])?t:null},t}(),e=function(){function e(){this.models=[],this._priorityQueue=new r,this.reset([])}return e.prototype=Object.create(t.Events),e.prototype.each=function(t,o){return this.models.forEach(t,o)},e.prototype.map=function(t,o){return this.models.map(t,o)},e.prototype._prepareModel=function(t){return t instanceof o?t:new o(t)},e.prototype.reset=function(t){var o,e,r,n,i,s,l;for(s=this.models,e=0,n=s.length;n>e;e++)o=s[e],o.off("all",this._onUploadEvent,this);for(this.models=function(){var e,r,n,i;for(n=null!=t?t:[],i=[],e=0,r=n.length;r>e;e++)o=n[e],i.push(this._prepareModel(o));return i}.call(this),this.length=this.models.length,this._idToModel={},l=this.models,r=0,i=l.length;i>r;r++)o=l[r],o.on("all",this._onUploadEvent,this),this._idToModel[o.id]=o;return this._priorityQueue.reset(this.models),this.trigger("reset",this)},e.prototype.get=function(t){var o;return null!=(o=this._idToModel[t])?o:null},e.prototype.forFile=function(t){return this.get(t.webkitRelativePath||t.name)},e.prototype.forFileInfo=function(t){return this.get(t.name)},e.prototype.addFiles=function(t){var e,r;return r=function(){var r,n,i;for(i=[],r=0,n=t.length;n>r;r++)e=t[r],i.push(new o({file:e}));return i}(),this._addWithMerge(r)},e.prototype.addFileInfos=function(t){var e,r;return r=function(){var r,n,i;for(i=[],r=0,n=t.length;n>r;r++)e=t[r],i.push(new o({fileInfo:e}));return i}(),this._addWithMerge(r)},e.prototype.next=function(){return this._priorityQueue.next()},e.prototype.add=function(t){return null!=t.length?this.addBatch(t):this.addBatch([t])},e.prototype.addBatch=function(t){var o,e,r,n,i;for(e=0,n=t.length;n>e;e++)o=t[e],this._idToModel[o.id]=o,o.on("all",this._onUploadEvent,this),this.models.push(o);for(this.length+=t.length,this._priorityQueue.addBatch(t),r=0,i=t.length;i>r;r++)o=t[r],this.trigger("add",o);return this.trigger("add-batch",t)},e.prototype._onUploadEvent=function(t,o){return"add"!==t&&"remove"!==t&&this.trigger.apply(this,arguments),"change"===t?this._priorityQueue.change(o):void 0},e.prototype._addWithMerge=function(t){var o,e,r,n,i,s,l;for(n=[],s=0,l=t.length;l>s;s++)i=t[s],null!=(o=this.get(i.id))?(e=i.get("file"),r=i.get("fileInfo"),null!=e&&o.set({file:e}),null!=r&&o.set({fileInfo:r})):n.push(i);return n.length&&this.add(n),void 0},e}()}),e("MassUpload/FileLister",[],function(){var t;return t=function(){function t(t,o){this.doListFiles=t,this.callbacks=o,this.running=!1}return t.prototype.run=function(){var t,o=this;if(this.running)throw"already running";return this.running=!0,"function"==typeof(t=this.callbacks).onStart&&t.onStart(),this.doListFiles(function(t){var e;return"function"==typeof(e=o.callbacks).onProgress?e.onProgress(t):void 0},function(t){return o._onSuccess(t)},function(t){return o._onError(t)})},t.prototype._onSuccess=function(t){var o;return"function"==typeof(o=this.callbacks).onSuccess&&o.onSuccess(t),this._onStop()},t.prototype._onError=function(t){return this.callbacks.onError(t),this._onStop()},t.prototype._onStop=function(){var t;return this.running=!1,"function"==typeof(t=this.callbacks).onStop?t.onStop():void 0},t}()}),e("MassUpload/FileUploader",["./FileInfo"],function(){var t;return t=function(){function t(t,o){this.doUpload=t,this.callbacks=o,this._file=null,this._abortCallback=null,this._aborting=!1}return t.prototype.run=function(t){var o,e=this;if(null!=this._file)throw"already running";return this._file=t,"function"==typeof(o=this.callbacks).onStart&&o.onStart(this._file),this._abortCallback=this.doUpload(t,function(o){return e._onProgress(t,o)},function(){return e._onSuccess(t)},function(o){return e._onError(t,o)})},t.prototype.abort=function(){return this._file&&!this._aborting&&(this._aborting=!0,"function"==typeof this._abortCallback)?this._abortCallback():void 0},t.prototype._onProgress=function(t,o){var e;return"function"==typeof(e=this.callbacks).onProgress?e.onProgress(t,o):void 0},t.prototype._onSuccess=function(t){var o;return"function"==typeof(o=this.callbacks).onSuccess&&o.onSuccess(t),this._onStop(t)},t.prototype._onError=function(t,o){var e;return"function"==typeof(e=this.callbacks).onError&&e.onError(t,o),this._onStop(t)},t.prototype._onStop=function(t){var o;return this._file=null,this._abortCallback=null,this._aborting=!1,"function"==typeof(o=this.callbacks).onStop?o.onStop(t):void 0},t}()}),e("MassUpload/FileDeleter",[],function(){var t;return t=function(){function t(t,o){this.doDeleteFile=t,this.callbacks=null!=o?o:{},this.running=!1}return t.prototype.run=function(t){var o,e=this;if(this.running)throw"already running";return this.running=!0,"function"==typeof(o=this.callbacks).onStart&&o.onStart(t),this.doDeleteFile(t,function(){return e._onSuccess(t)},function(o){return e._onError(t,o)})},t.prototype._onSuccess=function(t){var o;return"function"==typeof(o=this.callbacks).onSuccess&&o.onSuccess(t),this._onStop(t)},t.prototype._onError=function(t,o){var e;return"function"==typeof(e=this.callbacks).onError&&e.onError(t,o),this._onStop(t)},t.prototype._onStop=function(t){var o;return this.running=!1,"function"==typeof(o=this.callbacks).onStop&&o.onStop(t),void 0},t}()}),e("MassUpload/State",[],function(){var t;return t=function(){function t(t){var o,e,r,n;null==t&&(t={}),this.loaded=null!=(o=t.loaded)?o:0,this.total=null!=(e=t.total)?e:0,this.status=null!=(r=t.status)?r:"waiting",this.errors=null!=(n=t.errors)?n:[]}return t.prototype._extend=function(o){var e,r,n,i;return new t({loaded:null!=(e=o.loaded)?e:this.loaded,total:null!=(r=o.total)?r:this.total,status:null!=(n=o.status)?n:this.status,errors:null!=(i=o.errors)?i:this.errors})},t.prototype.isComplete=function(){return this.total&&this.loaded===this.total&&"waiting"===this.status&&!this.errors.length&&!0||!1},t.prototype.withTotal=function(t){return this._extend({total:t})},t.prototype.withLoaded=function(t){return this._extend({loaded:t})},t.prototype.withStatus=function(t){return this._extend({status:t})},t.prototype.withAnError=function(t){var o;return o=this.errors.slice(0),o.push(t),this._extend({errors:o})},t.prototype.withoutAnError=function(t){var o,e;return e=this.errors.slice(0),o=e.indexOf(t),e.splice(o,1),this._extend({errors:e})},t}()}),e("MassUpload/UploadProgress",["backbone"],function(t){return t.Model.extend({defaults:{loaded:0,total:0},initialize:function(){var t;if(t=this.get("uploadCollection"),null==t)throw"Must initialize UploadProgress with `uploadCollection`, an UploadCollection";return this._idToLastKnownProgress={},this._updateAndStartListening()},_adjust:function(t,o){return this.set({loaded:this.get("loaded")+t,total:this.get("total")+o})},add:function(t){var o;return o=t.getProgress(),this._adjust(o.loaded,o.total),this._idToLastKnownProgress[t.id]=o},reset:function(t){var o,e,r,n,i,s,l,u;for(o=this._idToLastKnownProgress={},e=0,i=0,u=t.models,s=0,l=u.length;l>s;s++)r=u[s],n=r.getProgress(),o[r.id]=n,e+=n.loaded,i+=n.total;return this.set({loaded:e,total:i})},remove:function(t){var o;return o=t.getProgress(),this._adjust(-o.loaded,-o.total),this._idToLastKnownProgress[t.id]=o},change:function(t){var o,e;return e=this._idToLastKnownProgress[t.id],null!=e?(o=t.getProgress(),this._adjust(o.loaded-e.loaded,o.total-e.total),this._idToLastKnownProgress[t.id]=o):void 0},_updateAndStartListening:function(){var t,o,e,r,n;for(t=this.get("uploadCollection"),n=["add","remove","change","reset"],e=0,r=n.length;r>e;e++)o=n[e],this.listenTo(t,o,this[o]);return this.reset(t),void 0},inBatch:function(t){this.stopListening(this.get("uploadCollection"));try{return t()}finally{this._updateAndStartListening()}}})});var r={}.hasOwnProperty,n=function(t,o){function e(){this.constructor=t}for(var n in o)r.call(o,n)&&(t[n]=o[n]);return e.prototype=o.prototype,t.prototype=new e,t.__super__=o.prototype,t};e("MassUpload",["backbone","underscore","MassUpload/UploadCollection","MassUpload/FileLister","MassUpload/FileUploader","MassUpload/FileDeleter","MassUpload/State","MassUpload/UploadProgress"],function(t,o,e,r,i,s,l,u){var a;return a=function(t){function l(t){this._removedUploads=[],l.__super__.constructor.call(this,{},t)}return n(l,t),l.prototype.defaults=function(){return{status:"waiting",listFilesProgress:null,listFilesError:null,uploadProgress:null,uploadErrors:[]}},l.prototype.initialize=function(t,o){var r,n,i=this;return this._options=o,this.uploads=null!=(n=null!=o?o.uploads:void 0)?n:new e,this._uploadProgress=new u({uploadCollection:this.uploads}),r=function(){return i.set({uploadProgress:i._uploadProgress.pick("loaded","total")})},this.listenTo(this._uploadProgress,"change",r),r(),this.listenTo(this.uploads,"add-batch",this._onUploadBatchAdded),this.listenTo(this.uploads,"change",function(t){return i._onUploadChanged(t)}),this.listenTo(this.uploads,"reset",function(){return i._onUploadsReset()}),this.prepare()},l.prototype.prepare=function(){var t,o,e,n,l=this;return t=this._options,this.lister=null!=(o=null!=t?t.lister:void 0)?o:new r(t.doListFiles),this.lister.callbacks={onStart:function(){return l._onListerStart()},onProgress:function(t){return l._onListerProgress(t)},onSuccess:function(t){return l._onListerSuccess(t)},onError:function(t){return l._onListerError(t)},onStop:function(){return l._onListerStop()}},this.uploader=null!=(e=null!=t?t.uploader:void 0)?e:new i(t.doUploadFile),this.uploader.callbacks={onStart:function(t){return l._onUploaderStart(t)},onStop:function(t){return l._onUploaderStop(t)},onSuccess:function(t){return l._onUploaderSuccess(t)},onError:function(t,o){return l._onUploaderError(t,o)},onProgress:function(t,o){return l._onUploaderProgress(t,o)}},this.deleter=null!=(n=null!=t?t.deleter:void 0)?n:new s(t.doDeleteFile),this.deleter.callbacks={onStart:function(t){return l._onDeleterStart(t)},onSuccess:function(t){return l._onDeleterSuccess(t)},onError:function(t,o){return l._onDeleterError(t,o)},onStop:function(t){return l._onDeleterStop(t)}}},l.prototype.fetchFileInfosFromServer=function(){return this.lister.run()},l.prototype.retryListFiles=function(){return this.fetchFileInfosFromServer()},l.prototype.retryUpload=function(t){return t.set({error:null})},l.prototype.retryAllUploads=function(){return this.uploads.each(function(t){return t.set({error:null})})},l.prototype.addFiles=function(t){var o=this;return this._uploadProgress.inBatch(function(){return o.uploads.addFiles(t)})},l.prototype.removeUpload=function(t){return t.set({deleting:!0})},l.prototype.abort=function(){var t=this;return this.uploads.each(function(o){return t.removeUpload(o)}),this.uploads.reset(),this.prepare()},l.prototype._onListerStart=function(){return this.set({status:"listing-files",listFilesError:null})},l.prototype._onListerProgress=function(t){return this.set({listFilesProgress:t})},l.prototype._onListerSuccess=function(t){return this.uploads.addFileInfos(t),this._tick()},l.prototype._onListerError=function(t){return this.set({listFilesError:t,status:"listing-files-error"})},l.prototype._onListerStop=function(){},l.prototype._mergeUploadError=function(t,e,r){var n,i;return i=this.get("uploadErrors").slice(0),n=o.sortedIndex(i,{upload:t},function(t){return t.upload.id}),null==e?i.splice(n,0,{upload:t,error:r}):null==r?i.splice(n,1):i[n].error=r,this.set({uploadErrors:i})},l.prototype._onUploadBatchAdded=function(t){var o,e,r,n;for(r=0,n=t.length;n>r;r++)e=t[r],o=e.get("error"),null!=o&&this._mergeUploadError(e,null,o);return this._forceBestTick()},l.prototype._onUploadChanged=function(t){var o,e,r,n;return r=t.previousAttributes().error,n=t.get("error"),r!==n&&this._mergeUploadError(t,r,n),o=t.previousAttributes().deleting,e=t.get("deleting"),e&&!o&&this._removedUploads.push(t),this._forceBestTick()},l.prototype._onUploadsReset=function(){var t;return t=[],this.uploads.each(function(o){var e;return(e=o.get("error"))?t.push({upload:o,error:e}):void 0}),this.set({uploadErrors:t}),this._tick()},l.prototype._onUploaderStart=function(t){var o;return o=this.uploads.forFile(t),o.set({uploading:!0,error:null})},l.prototype._onUploaderStop=function(t){var o;return o=this.uploads.forFile(t),o.set({uploading:!1}),this._tick()},l.prototype._onUploaderProgress=function(t,o){var e;return e=this.uploads.forFile(t),e.updateWithProgress(o)},l.prototype._onUploaderError=function(t,o){var e;return e=this.uploads.forFile(t),e.set({error:o})},l.prototype._onUploaderSuccess=function(t){var o;return o=this.uploads.forFile(t),o.updateWithProgress({loaded:o.size(),total:o.size()})},l.prototype._onDeleterStart=function(){return this.set({status:"uploading"})},l.prototype._onDeleterSuccess=function(t){var o;return o=this.uploads.forFileInfo(t),this.uploads.remove(o)},l.prototype._onDeleterError=function(t,o){var e;return e=this.uploads.forFileInfo(t),e.set({error:o})},l.prototype._onDeleterStop=function(){return this._tick()},l.prototype._tick=function(){var t,o,e;return e=this.uploads.next(),this._currentUpload=e,null!=e&&(e.get("deleting")?this.deleter.run(e.get("fileInfo")):this.uploader.run(e.get("file"))),o=this.get("uploadErrors").length?"uploading-error":null!=e?"uploading":(t=this.get("uploadProgress"),t.loaded===t.total?"waiting":"waiting-error"),this.set({status:o})},l.prototype._forceBestTick=function(){var t;return t=this.uploads.next(),t!==this._currentUpload?this._currentUpload?this.uploader.abort():this._tick():void 0},l}(t.Model)}),o(["./MassUpload"],function(t){return window.MassUpload=t}),e("index",function(){})}(); \ No newline at end of file diff --git a/gulpfile.coffee b/gulpfile.coffee new file mode 100644 index 0000000..3838527 --- /dev/null +++ b/gulpfile.coffee @@ -0,0 +1,72 @@ +browserify = require('browserify') +coffeeify = require('coffeeify') +derequire = require('gulp-derequire') +gulp = require('gulp') +gutil = require('gulp-util') +karma = require('karma').server +rename = require('gulp-rename') +rimraf = require('gulp-rimraf') +source = require('vinyl-source-stream') +uglify = require('gulp-uglify') + +gulp.task 'clean', -> + gulp.src('./js-mass-upload*.js', read: false) + .pipe(rimraf()) + +gulp.task 'clean-demo', -> + gulp.src('./demo/js', read: false) + .pipe(rimraf()) + +gulp.task 'browserify', [ 'clean' ], -> + b = browserify('./src/MassUpload.coffee', { + extensions: [ '.js', '.coffee' ] + standalone: 'MassUpload' + }) + b.transform(coffeeify) + + b.bundle() + .on('error', (e) -> gutil.log('Browserify error', e)) + .pipe(source('js-mass-upload.js')) + .pipe(derequire()) + .pipe(gulp.dest('.')) + +gulp.task 'browserify-demo', [ 'browserify', 'clean-demo' ], -> + b = browserify('./app.coffee', { + extensions: [ '.js', '.coffee' ] + basedir: './demo/coffee' + }) + b.transform(coffeeify) + + b.bundle() + .on('error', (e) -> gutil.log('Browserify error', e)) + .pipe(source('app.js')) + .pipe(derequire()) + .pipe(gulp.dest('./demo/js')) + +gulp.task 'minify', [ 'browserify' ], -> + gulp.src('js-mass-upload.js') + .pipe(uglify()) + .pipe(rename(suffix: '.min')) + .pipe(gulp.dest('.')) + +gulp.task 'test-browser', (done) -> + karma.start({ + singleRun: true + browsers: [ 'PhantomJS' ] + frameworks: [ 'browserify', 'mocha' ] + reporters: [ 'dots' ] + browserify: + debug: true + extensions: [ '.js', '.coffee' ] + transform: [ coffeeify ] + files: [ + 'test/init.coffee' + { pattern: 'test/**/*Spec.coffee' } + ] + preprocessors: + '**/*.coffee': 'browserify' + }, done) + +gulp.task('test', [ 'test-browser' ]) + +gulp.task('default', [ 'minify', 'browserify-demo' ]) diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..c7f2b8b --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,2 @@ +require('coffee-script/register'); +require('./gulpfile.coffee'); diff --git a/js-mass-upload.js b/js-mass-upload.js new file mode 100644 index 0000000..b9da1fb --- /dev/null +++ b/js-mass-upload.js @@ -0,0 +1,4180 @@ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.MassUpload=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o').attr(attrs); + this.setElement($el, false); + } else { + this.setElement(_.result(this, 'el'), false); + } + } + + }); + + // Backbone.sync + // ------------- + + // Override this function to change the manner in which Backbone persists + // models to the server. You will be passed the type of request, and the + // model in question. By default, makes a RESTful Ajax request + // to the model's `url()`. Some possible customizations could be: + // + // * Use `setTimeout` to batch rapid-fire updates into a single request. + // * Send up the models as XML instead of JSON. + // * Persist models via WebSockets instead of Ajax. + // + // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests + // as `POST`, with a `_method` parameter containing the true HTTP method, + // as well as all requests with the body as `application/x-www-form-urlencoded` + // instead of `application/json` with the model in a param named `model`. + // Useful when interfacing with server-side languages like **PHP** that make + // it difficult to read the body of `PUT` requests. + Backbone.sync = function(method, model, options) { + var type = methodMap[method]; + + // Default options, unless specified. + _.defaults(options || (options = {}), { + emulateHTTP: Backbone.emulateHTTP, + emulateJSON: Backbone.emulateJSON + }); + + // Default JSON-request options. + var params = {type: type, dataType: 'json'}; + + // Ensure that we have a URL. + if (!options.url) { + params.url = _.result(model, 'url') || urlError(); + } + + // Ensure that we have the appropriate request data. + if (options.data == null && model && (method === 'create' || method === 'update' || method === 'patch')) { + params.contentType = 'application/json'; + params.data = JSON.stringify(options.attrs || model.toJSON(options)); + } + + // For older servers, emulate JSON by encoding the request into an HTML-form. + if (options.emulateJSON) { + params.contentType = 'application/x-www-form-urlencoded'; + params.data = params.data ? {model: params.data} : {}; + } + + // For older servers, emulate HTTP by mimicking the HTTP method with `_method` + // And an `X-HTTP-Method-Override` header. + if (options.emulateHTTP && (type === 'PUT' || type === 'DELETE' || type === 'PATCH')) { + params.type = 'POST'; + if (options.emulateJSON) params.data._method = type; + var beforeSend = options.beforeSend; + options.beforeSend = function(xhr) { + xhr.setRequestHeader('X-HTTP-Method-Override', type); + if (beforeSend) return beforeSend.apply(this, arguments); + }; + } + + // Don't process data on a non-GET request. + if (params.type !== 'GET' && !options.emulateJSON) { + params.processData = false; + } + + // If we're sending a `PATCH` request, and we're in an old Internet Explorer + // that still has ActiveX enabled by default, override jQuery to use that + // for XHR instead. Remove this line when jQuery supports `PATCH` on IE8. + if (params.type === 'PATCH' && noXhrPatch) { + params.xhr = function() { + return new ActiveXObject("Microsoft.XMLHTTP"); + }; + } + + // Make the request, allowing the user to override any Ajax options. + var xhr = options.xhr = Backbone.ajax(_.extend(params, options)); + model.trigger('request', model, xhr, options); + return xhr; + }; + + var noXhrPatch = + typeof window !== 'undefined' && !!window.ActiveXObject && + !(window.XMLHttpRequest && (new XMLHttpRequest).dispatchEvent); + + // Map from CRUD to HTTP for our default `Backbone.sync` implementation. + var methodMap = { + 'create': 'POST', + 'update': 'PUT', + 'patch': 'PATCH', + 'delete': 'DELETE', + 'read': 'GET' + }; + + // Set the default implementation of `Backbone.ajax` to proxy through to `$`. + // Override this if you'd like to use a different library. + Backbone.ajax = function() { + return Backbone.$.ajax.apply(Backbone.$, arguments); + }; + + // Backbone.Router + // --------------- + + // Routers map faux-URLs to actions, and fire events when routes are + // matched. Creating a new one sets its `routes` hash, if not set statically. + var Router = Backbone.Router = function(options) { + options || (options = {}); + if (options.routes) this.routes = options.routes; + this._bindRoutes(); + this.initialize.apply(this, arguments); + }; + + // Cached regular expressions for matching named param parts and splatted + // parts of route strings. + var optionalParam = /\((.*?)\)/g; + var namedParam = /(\(\?)?:\w+/g; + var splatParam = /\*\w+/g; + var escapeRegExp = /[\-{}\[\]+?.,\\\^$|#\s]/g; + + // Set up all inheritable **Backbone.Router** properties and methods. + _.extend(Router.prototype, Events, { + + // Initialize is an empty function by default. Override it with your own + // initialization logic. + initialize: function(){}, + + // Manually bind a single named route to a callback. For example: + // + // this.route('search/:query/p:num', 'search', function(query, num) { + // ... + // }); + // + route: function(route, name, callback) { + if (!_.isRegExp(route)) route = this._routeToRegExp(route); + if (_.isFunction(name)) { + callback = name; + name = ''; + } + if (!callback) callback = this[name]; + var router = this; + Backbone.history.route(route, function(fragment) { + var args = router._extractParameters(route, fragment); + router.execute(callback, args); + router.trigger.apply(router, ['route:' + name].concat(args)); + router.trigger('route', name, args); + Backbone.history.trigger('route', router, name, args); + }); + return this; + }, + + // Execute a route handler with the provided parameters. This is an + // excellent place to do pre-route setup or post-route cleanup. + execute: function(callback, args) { + if (callback) callback.apply(this, args); + }, + + // Simple proxy to `Backbone.history` to save a fragment into the history. + navigate: function(fragment, options) { + Backbone.history.navigate(fragment, options); + return this; + }, + + // Bind all defined routes to `Backbone.history`. We have to reverse the + // order of the routes here to support behavior where the most general + // routes can be defined at the bottom of the route map. + _bindRoutes: function() { + if (!this.routes) return; + this.routes = _.result(this, 'routes'); + var route, routes = _.keys(this.routes); + while ((route = routes.pop()) != null) { + this.route(route, this.routes[route]); + } + }, + + // Convert a route string into a regular expression, suitable for matching + // against the current location hash. + _routeToRegExp: function(route) { + route = route.replace(escapeRegExp, '\\$&') + .replace(optionalParam, '(?:$1)?') + .replace(namedParam, function(match, optional) { + return optional ? match : '([^/?]+)'; + }) + .replace(splatParam, '([^?]*?)'); + return new RegExp('^' + route + '(?:\\?([\\s\\S]*))?$'); + }, + + // Given a route, and a URL fragment that it matches, return the array of + // extracted decoded parameters. Empty or unmatched parameters will be + // treated as `null` to normalize cross-browser behavior. + _extractParameters: function(route, fragment) { + var params = route.exec(fragment).slice(1); + return _.map(params, function(param, i) { + // Don't decode the search params. + if (i === params.length - 1) return param || null; + return param ? decodeURIComponent(param) : null; + }); + } + + }); + + // Backbone.History + // ---------------- + + // Handles cross-browser history management, based on either + // [pushState](http://diveintohtml5.info/history.html) and real URLs, or + // [onhashchange](https://developer.mozilla.org/en-US/docs/DOM/window.onhashchange) + // and URL fragments. If the browser supports neither (old IE, natch), + // falls back to polling. + var History = Backbone.History = function() { + this.handlers = []; + _.bindAll(this, 'checkUrl'); + + // Ensure that `History` can be used outside of the browser. + if (typeof window !== 'undefined') { + this.location = window.location; + this.history = window.history; + } + }; + + // Cached regex for stripping a leading hash/slash and trailing space. + var routeStripper = /^[#\/]|\s+$/g; + + // Cached regex for stripping leading and trailing slashes. + var rootStripper = /^\/+|\/+$/g; + + // Cached regex for detecting MSIE. + var isExplorer = /msie [\w.]+/; + + // Cached regex for removing a trailing slash. + var trailingSlash = /\/$/; + + // Cached regex for stripping urls of hash. + var pathStripper = /#.*$/; + + // Has the history handling already been started? + History.started = false; + + // Set up all inheritable **Backbone.History** properties and methods. + _.extend(History.prototype, Events, { + + // The default interval to poll for hash changes, if necessary, is + // twenty times a second. + interval: 50, + + // Are we at the app root? + atRoot: function() { + return this.location.pathname.replace(/[^\/]$/, '$&/') === this.root; + }, + + // Gets the true hash value. Cannot use location.hash directly due to bug + // in Firefox where location.hash will always be decoded. + getHash: function(window) { + var match = (window || this).location.href.match(/#(.*)$/); + return match ? match[1] : ''; + }, + + // Get the cross-browser normalized URL fragment, either from the URL, + // the hash, or the override. + getFragment: function(fragment, forcePushState) { + if (fragment == null) { + if (this._hasPushState || !this._wantsHashChange || forcePushState) { + fragment = decodeURI(this.location.pathname + this.location.search); + var root = this.root.replace(trailingSlash, ''); + if (!fragment.indexOf(root)) fragment = fragment.slice(root.length); + } else { + fragment = this.getHash(); + } + } + return fragment.replace(routeStripper, ''); + }, + + // Start the hash change handling, returning `true` if the current URL matches + // an existing route, and `false` otherwise. + start: function(options) { + if (History.started) throw new Error("Backbone.history has already been started"); + History.started = true; + + // Figure out the initial configuration. Do we need an iframe? + // Is pushState desired ... is it available? + this.options = _.extend({root: '/'}, this.options, options); + this.root = this.options.root; + this._wantsHashChange = this.options.hashChange !== false; + this._wantsPushState = !!this.options.pushState; + this._hasPushState = !!(this.options.pushState && this.history && this.history.pushState); + var fragment = this.getFragment(); + var docMode = document.documentMode; + var oldIE = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7)); + + // Normalize root to always include a leading and trailing slash. + this.root = ('/' + this.root + '/').replace(rootStripper, '/'); + + if (oldIE && this._wantsHashChange) { + var frame = Backbone.$('