uploads 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +3 -0
  3. data/Rakefile +38 -0
  4. data/app/assets/javascripts/anjlab/uploads.js +7 -0
  5. data/app/assets/javascripts/anjlab/uploads/button.js.coffee +80 -0
  6. data/app/assets/javascripts/anjlab/uploads/dnd.js.coffee +215 -0
  7. data/app/assets/javascripts/anjlab/uploads/handler.base.js.coffee +101 -0
  8. data/app/assets/javascripts/anjlab/uploads/handler.form.js.coffee +173 -0
  9. data/app/assets/javascripts/anjlab/uploads/handler.xhr.js.coffee +393 -0
  10. data/app/assets/javascripts/anjlab/uploads/uploader.js.coffee +487 -0
  11. data/app/assets/javascripts/anjlab/uploads/utils.js.coffee +116 -0
  12. data/lib/tasks/uploads_tasks.rake +4 -0
  13. data/lib/uploads.rb +10 -0
  14. data/lib/uploads/engine.rb +6 -0
  15. data/lib/uploads/version.rb +3 -0
  16. data/test/dummy/README.rdoc +261 -0
  17. data/test/dummy/Rakefile +7 -0
  18. data/test/dummy/app/assets/javascripts/application.js +16 -0
  19. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  20. data/test/dummy/app/controllers/application_controller.rb +3 -0
  21. data/test/dummy/app/controllers/uploads_controller.rb +15 -0
  22. data/test/dummy/app/controllers/welcome_controller.rb +4 -0
  23. data/test/dummy/app/helpers/application_helper.rb +2 -0
  24. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  25. data/test/dummy/app/views/welcome/index.html.slim +53 -0
  26. data/test/dummy/config.ru +4 -0
  27. data/test/dummy/config/application.rb +59 -0
  28. data/test/dummy/config/boot.rb +10 -0
  29. data/test/dummy/config/database.yml +25 -0
  30. data/test/dummy/config/environment.rb +5 -0
  31. data/test/dummy/config/environments/development.rb +37 -0
  32. data/test/dummy/config/environments/production.rb +67 -0
  33. data/test/dummy/config/environments/test.rb +37 -0
  34. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  35. data/test/dummy/config/initializers/inflections.rb +15 -0
  36. data/test/dummy/config/initializers/mime_types.rb +5 -0
  37. data/test/dummy/config/initializers/secret_token.rb +7 -0
  38. data/test/dummy/config/initializers/session_store.rb +8 -0
  39. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  40. data/test/dummy/config/locales/en.yml +5 -0
  41. data/test/dummy/config/routes.rb +59 -0
  42. data/test/dummy/db/development.sqlite3 +0 -0
  43. data/test/dummy/log/development.log +23847 -0
  44. data/test/dummy/public/404.html +26 -0
  45. data/test/dummy/public/422.html +26 -0
  46. data/test/dummy/public/500.html +25 -0
  47. data/test/dummy/public/favicon.ico +0 -0
  48. data/test/dummy/script/rails +6 -0
  49. data/test/dummy/tmp/cache/assets/C79/790/sprockets%2Fde97a756642791010533233b267b1afe +0 -0
  50. data/test/dummy/tmp/cache/assets/C99/300/sprockets%2F3bd289b286c074ad66220ad20181b135 +0 -0
  51. data/test/dummy/tmp/cache/assets/C9E/CA0/sprockets%2F1252e234767209f94d0a41a0bc19e33c +0 -0
  52. data/test/dummy/tmp/cache/assets/CA1/9E0/sprockets%2F4c40d59c233952767c150cb8234cab22 +0 -0
  53. data/test/dummy/tmp/cache/assets/CA5/AC0/sprockets%2Fcc77204615926b95033b4fa044d7c61b +0 -0
  54. data/test/dummy/tmp/cache/assets/CAA/860/sprockets%2F6b1d0c998769132cda15f7c5d1283300 +0 -0
  55. data/test/dummy/tmp/cache/assets/CCD/830/sprockets%2F962b2259b044ca05005c14fd83ba982a +0 -0
  56. data/test/dummy/tmp/cache/assets/CD2/7B0/sprockets%2Fe9a64cf98e26a4719e64d747d7912893 +0 -0
  57. data/test/dummy/tmp/cache/assets/CD8/370/sprockets%2F357970feca3ac29060c1e3861e2c0953 +0 -0
  58. data/test/dummy/tmp/cache/assets/CE4/A00/sprockets%2Fe589f936724000ba0e7f077a63b75d4e +0 -0
  59. data/test/dummy/tmp/cache/assets/CE7/D40/sprockets%2F888fd320a7c0125218313f1ef9d6d99d +0 -0
  60. data/test/dummy/tmp/cache/assets/CFD/650/sprockets%2F73de09397391979f4dcd67ce32a7816f +0 -0
  61. data/test/dummy/tmp/cache/assets/D07/710/sprockets%2F56976babbbfe475040b22885733ca41a +0 -0
  62. data/test/dummy/tmp/cache/assets/D0B/D70/sprockets%2F6c298d94014122a613afbebce90590f8 +0 -0
  63. data/test/dummy/tmp/cache/assets/D0F/6A0/sprockets%2F18414faf9678c2ab6d1d60891c6f06a1 +0 -0
  64. data/test/dummy/tmp/cache/assets/D15/C40/sprockets%2F5516d9e4e25aaefc72a78fc641962512 +0 -0
  65. data/test/dummy/tmp/cache/assets/D24/CD0/sprockets%2Fd0cd795c6f0b6074de96706e8bf70975 +0 -0
  66. data/test/dummy/tmp/cache/assets/D2E/980/sprockets%2Fded84d1bb4c31404691d106f4b8e120f +0 -0
  67. data/test/dummy/tmp/cache/assets/D32/A10/sprockets%2F13fe41fee1fe35b49d145bcc06610705 +0 -0
  68. data/test/dummy/tmp/cache/assets/D33/120/sprockets%2F70d8b84b628400ffbf410b17b845bae2 +0 -0
  69. data/test/dummy/tmp/cache/assets/D35/8C0/sprockets%2F20424272a569797e71dbae1bdb33c2fc +0 -0
  70. data/test/dummy/tmp/cache/assets/D3F/FE0/sprockets%2Fbfc6e8a285039670d3ca0399bd3e633b +0 -0
  71. data/test/dummy/tmp/cache/assets/D44/E50/sprockets%2F5767c31d95e72a26ffb3c0092dc3cf94 +0 -0
  72. data/test/dummy/tmp/cache/assets/D48/8B0/sprockets%2F795b331f7ff4a59f0604c531e71af9de +0 -0
  73. data/test/dummy/tmp/cache/assets/D4D/420/sprockets%2Fab27b88913d73cdabe65891eeb884444 +0 -0
  74. data/test/dummy/tmp/cache/assets/D4E/1B0/sprockets%2Ff7cbd26ba1d28d48de824f0e94586655 +0 -0
  75. data/test/dummy/tmp/cache/assets/D5A/2A0/sprockets%2Fc379b9f699c8f614cefea762d376d224 +0 -0
  76. data/test/dummy/tmp/cache/assets/D5A/EA0/sprockets%2Fd771ace226fc8215a3572e0aa35bb0d6 +0 -0
  77. data/test/dummy/tmp/cache/assets/D5D/330/sprockets%2Fce164ed2c0f3e91b338035376ad41bac +0 -0
  78. data/test/dummy/tmp/cache/assets/D6D/350/sprockets%2Fdac0344fd04f6fe00bce8983177635ea +0 -0
  79. data/test/dummy/tmp/cache/assets/D71/6E0/sprockets%2F07996d57b5cfca8a92b02613fdaae735 +0 -0
  80. data/test/dummy/tmp/cache/assets/D7C/210/sprockets%2Ff98c0ec43e4406aa3cec29837d9f618e +0 -0
  81. data/test/dummy/tmp/cache/assets/D7E/AF0/sprockets%2F1d4ffb9a3d536682ff7d185668dc2d4b +0 -0
  82. data/test/dummy/tmp/cache/assets/D96/9A0/sprockets%2Ff1caf4ea19ee66a13841eaf6f40a6433 +0 -0
  83. data/test/dummy/tmp/cache/assets/D97/760/sprockets%2Fd1c9a476956a0ccae81fa57dad53135a +0 -0
  84. data/test/dummy/tmp/cache/assets/DBB/F20/sprockets%2F03e6ee44546ae1ea1bfd3e0801b7ca7a +0 -0
  85. data/test/dummy/tmp/cache/assets/DC3/810/sprockets%2Fc86e769b165de4f9d49745ab9fee7b5f +0 -0
  86. data/test/dummy/tmp/cache/assets/DC5/3C0/sprockets%2Fc21f1ad7fdce18f5b7a5a581b1351fd6 +0 -0
  87. data/test/dummy/tmp/cache/assets/DCA/4A0/sprockets%2Fbdfe27f0efa249de171cbfb2970661c2 +0 -0
  88. data/test/dummy/tmp/cache/assets/DD3/AF0/sprockets%2Fb090f4fd52cbc2e5ccc815aa8999f2f3 +0 -0
  89. data/test/dummy/tmp/cache/assets/DDC/400/sprockets%2Fcffd775d018f68ce5dba1ee0d951a994 +0 -0
  90. data/test/dummy/tmp/cache/assets/DE7/920/sprockets%2Feea789b2f9e87ceaffa7757e32fd1192 +0 -0
  91. data/test/dummy/tmp/cache/assets/E02/FE0/sprockets%2F68a4afe37ab83b2d9fa1cf5e084fec81 +0 -0
  92. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  93. data/test/dummy/tmp/cache/assets/E2B/C80/sprockets%2Ff6f179d2c6207aabbc3cec5c260eee9e +0 -0
  94. data/test/dummy/tmp/cache/assets/E47/5F0/sprockets%2Fef5f1e3bcbc9baa50e54a15ba0e5ca91 +0 -0
  95. data/test/test_helper.rb +15 -0
  96. data/test/uploads_test.rb +7 -0
  97. metadata +276 -0
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
1
+ = Uploads
2
+
3
+ This project rocks and uses MIT-LICENSE.
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'Uploads'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
28
+ require 'rake/testtask'
29
+
30
+ Rake::TestTask.new(:test) do |t|
31
+ t.libs << 'lib'
32
+ t.libs << 'test'
33
+ t.pattern = 'test/**/*_test.rb'
34
+ t.verbose = false
35
+ end
36
+
37
+
38
+ task :default => :test
@@ -0,0 +1,7 @@
1
+ // =require anjlab/uploads/utils
2
+ // =require anjlab/uploads/handler.base
3
+ // =require anjlab/uploads/handler.form
4
+ // =require anjlab/uploads/handler.xhr
5
+ // =require anjlab/uploads/button
6
+ // =require anjlab/uploads/dnd
7
+ // =require anjlab/uploads/uploader
@@ -0,0 +1,80 @@
1
+ class @AnjLab.Uploads.Button
2
+
3
+ constructor: (element, options) ->
4
+ @options = $.extend(true, {}, $.fn.uploaderButtonDefaults, options)
5
+ @$element = $(@options.element ? element)
6
+
7
+ # make button suitable container for input
8
+ @$element.css
9
+ position: 'relative'
10
+ overflow: 'hidden'
11
+ # Make sure browse button is in the right side
12
+ # in Internet Explorer
13
+ direction: 'ltr'
14
+
15
+ @input = @createInput()
16
+
17
+ getInput: -> @input
18
+
19
+ # cleans/recreates the file input
20
+ reset: ->
21
+ if @input.parentNode
22
+ $(@input).remove()
23
+
24
+ @$element.removeClass(@options.focusClass)
25
+ @input = @createInput()
26
+
27
+ createInput: ->
28
+ input = document.createElement("input")
29
+
30
+ if @options.multiple
31
+ input.setAttribute("multiple", "multiple")
32
+
33
+ if @options.acceptFiles
34
+ input.setAttribute("accept", @options.acceptFiles)
35
+
36
+ input.setAttribute("type", "file")
37
+ input.setAttribute("name", @options.name)
38
+
39
+ $(input).css
40
+ position: 'absolute'
41
+ # in Opera only 'browse' button
42
+ # is clickable and it is located at
43
+ # the right side of the input
44
+ right: 0
45
+ top: 0
46
+ fontFamily: 'Arial'
47
+ # 4 persons reported this, the max values that worked for them were 243, 236, 236, 118
48
+ fontSize: '118px'
49
+ margin: 0
50
+ padding: 0
51
+ cursor: 'pointer'
52
+ opacity: 0
53
+
54
+ @$element.append(input)
55
+
56
+ $(input).on
57
+ change: => @options.onChange(input)
58
+ mouseover: => @$element.addClass(@options.hoverClass)
59
+ mouseout: => @$element.removeClass(@options.hoverClass)
60
+ focus: => @$element.addClass(@options.focusClass)
61
+ blur: => @$element.removeClass(@options.focusClass)
62
+
63
+ # IE and Opera, unfortunately have 2 tab stops on file input
64
+ # which is unacceptable in our case, disable keyboard access
65
+ if window.attachEvent
66
+ # it is IE or Opera
67
+ input.setAttribute('tabIndex', '-1')
68
+
69
+ input
70
+
71
+ $.fn.uploaderButtonDefaults =
72
+ element: null
73
+ # if set to true adds multiple attribute to file input
74
+ multiple: false,
75
+ acceptFiles: null,
76
+ # name attribute of file input
77
+ name: 'file',
78
+ onChange: (input) -> null,
79
+ hoverClass: 'qq-upload-button-hover',
80
+ focusClass: 'qq-upload-button-focus'
@@ -0,0 +1,215 @@
1
+ utils = @AnjLab.Uploads.Utils
2
+
3
+ class @AnjLab.Uploads.DragAndDrop
4
+
5
+ constructor: (zones, options)->
6
+ @droppedFiles = []
7
+ @droppedEntriesCount = 0
8
+ @droppedEntriesParsedCount = 0
9
+ @options = options
10
+ @setupDragDrop(zones)
11
+
12
+ maybeUploadDroppedFiles: ->
13
+ if @droppedEntriesCount == @droppedEntriesParsedCount && !@dirPending
14
+ @options.callbacks.log("Grabbed #{@droppedFiles.length} files after tree traversal.")
15
+ @zones.each -> $(this).data('dropZone').dropDisabled(false)
16
+ @options.callbacks.dropProcessing(false, @droppedFiles)
17
+
18
+ addDroppedFile: (file)->
19
+ @droppedFiles.push(file)
20
+ @droppedEntriesParsedCount += 1
21
+ @maybeUploadDroppedFiles()
22
+
23
+ traverseFileTree: (entry)->
24
+ # var dirReader, i;
25
+ dirPending = false
26
+ @droppedEntriesCount+=1
27
+
28
+ if entry.isFile
29
+ entry.file (file) => @addDroppedFile(file)
30
+ else if entry.isDirectory
31
+ dirPending = true
32
+ dirReader = entry.createReader();
33
+ dirReader.readEntries (entries) =>
34
+ @droppedEntriesParsedCount+=1;
35
+ for e in entries
36
+ @traverseFileTree(e)
37
+
38
+ dirPending = false;
39
+
40
+ if !entries.length
41
+ @maybeUploadDroppedFiles()
42
+
43
+ isFileDrag: (dragEvent) ->
44
+ for own key, val of dragEvent.dataTransfer.types
45
+ return true if val == 'Files'
46
+
47
+ false
48
+
49
+ handleDataTransfer: (dataTransfer) ->
50
+ @options.callbacks.dropProcessing(true)
51
+ @zones.each -> $(this).data('dropZone').dropDisabled(true)
52
+
53
+ if dataTransfer.files.length > 1 && !@options.multiple
54
+ @options.callbacks.dropProcessing(false)
55
+ @options.callbacks.error('tooManyFilesError', "")
56
+ @zones.each -> $(this).data('dropZone').dropDisabled(false)
57
+ else
58
+ @droppedFiles = [];
59
+ @droppedEntriesCount = 0
60
+ @droppedEntriesParsedCount = 0
61
+
62
+ if utils.isFolderDropSupported(dataTransfer)
63
+ items = dataTransfer.items
64
+
65
+ i = 0
66
+ for item in items
67
+ entry = item.webkitGetAsEntry()
68
+ if entry
69
+ # due to a bug in Chrome's File System API impl - #149735
70
+ if entry.isFile
71
+ @droppedFiles.push(items[i].getAsFile());
72
+ if (i == items.length - 1)
73
+ @maybeUploadDroppedFiles()
74
+ else
75
+ @traverseFileTree(entry)
76
+ i += 1
77
+ else
78
+ @options.callbacks.dropProcessing(false, dataTransfer.files)
79
+ @zones.each -> $(this).data('dropZone').dropDisabled(false)
80
+
81
+ setupDragDrop: (zones)->
82
+ dnd = this
83
+ @zones = $(zones).each ->
84
+ $zone = $(this)
85
+ zoneOpts = $.extend(true, {}, {
86
+ onEnter: (e) =>
87
+ $zone.toggleClass(dnd.options.classes.dropActive, true)
88
+ e.stopPropagation()
89
+
90
+ onLeaveNotDescendants: (e) =>
91
+ $zone.toggleClass(dnd.options.classes.dropActive, false)
92
+
93
+ onDrop: (e) =>
94
+ $zone.toggleClass(dnd.options.classes.dropActive, false)
95
+
96
+ dnd.handleDataTransfer(e.originalEvent.dataTransfer)
97
+ }, dnd.options)
98
+
99
+ $zone.data('dropZone', new AnjLab.Uploads.UploadDropZone(this, zoneOpts))
100
+
101
+ $(document).on 'drop', (e) -> e.preventDefault()
102
+
103
+ _dropOutsideDisabled = false
104
+ _collection = $()
105
+
106
+ class @AnjLab.Uploads.UploadDropZone
107
+
108
+ constructor: (element, options)->
109
+ @$element = $(element)
110
+
111
+ defaultOptions =
112
+ onEnter: (e) -> null
113
+ onLeave: (e) -> null
114
+ # is not fired when leaving element by hovering descendants
115
+ onLeaveNotDescendants: (e) -> null,
116
+ onDrop: (e) -> null
117
+
118
+ @options = $.extend(true, {}, defaultOptions, options)
119
+
120
+ @disableDropOutside()
121
+ @attachEvents()
122
+
123
+ docDragEnter:(e)->
124
+ if (_collection.size() == 0)
125
+ $('body').toggleClass(@options.classes.bodyDragover, true)
126
+ _collection = _collection.add(e.target)
127
+
128
+ docDragLeave:(e)->
129
+ #timeout is needed because Firefox 3.6 fires the dragleave event on
130
+ # the previous element before firing dragenter on the next one
131
+ setTimeout( =>
132
+ # remove 'left' element from the collection
133
+ _collection = _collection.not(e.target)
134
+
135
+ # if collection is empty we have left the original element
136
+ # (dragleave has fired on all 'entered' elements)
137
+ if _collection.size() == 0
138
+ $('body').toggleClass(@options.classes.bodyDragover, false)
139
+ , 1)
140
+
141
+ disableDropOutside: (e) ->
142
+ # run only once for all instances
143
+ if !_dropOutsideDisabled
144
+
145
+ $(document).on 'dragover', (e)->
146
+ if e.originalEvent.dataTransfer
147
+ e.originalEvent.dataTransfer.dropEffect = 'none'
148
+ e.preventDefault()
149
+ false
150
+
151
+ $(document).on 'dragenter', (e) => @docDragEnter(e)
152
+
153
+ $(document).on 'dragleave drop', (e)=> @docDragLeave(e)
154
+
155
+ _dropOutsideDisabled = true
156
+
157
+ isValidFileDrag: (e)->
158
+ # e.dataTransfer currently causing IE errors
159
+ # IE9 does NOT support file API, so drag-and-drop is not possible
160
+ return false if utils.ie() && !utils.ie10()
161
+
162
+ dt = e.originalEvent.dataTransfer
163
+ # do not check dt.types.contains in webkit, because it crashes safari 4
164
+ isSafari = utils.safari()
165
+
166
+ # dt.effectAllowed is none in Safari 5
167
+ # dt.types.contains check is for firefox
168
+ effectTest = if utils.ie10() then true else dt.effectAllowed != 'none'
169
+ dt && effectTest && (dt.files || (!isSafari && dt.types.contains && dt.types.contains('Files')))
170
+
171
+ isOrSetDropDisabled: (isDisabled)->
172
+ @preventDrop = isDisabled if isDisabled != undefined
173
+ @preventDrop
174
+
175
+ attachEvents: ->
176
+ @$element.on 'dragover', (e) =>
177
+ return if !@isValidFileDrag(e)
178
+
179
+ effect = if utils.ie() ? null else e.originalEvent.dataTransfer.effectAllowed
180
+ if effect == 'move' || effect == 'linkMove'
181
+ e.originalEvent.dataTransfer.dropEffect = 'move' # for FF (only move allowed)
182
+ else
183
+ e.originalEvent.dataTransfer.dropEffect = 'copy' # for Chrome
184
+
185
+ e.stopPropagation()
186
+ e.preventDefault()
187
+ false
188
+
189
+ @$element.on 'dragenter', (e) =>
190
+ @docDragEnter(e)
191
+ if !@isOrSetDropDisabled()
192
+ return if !@isValidFileDrag(e)
193
+ @options.onEnter(e)
194
+
195
+ @$element.on 'dragleave', (e) =>
196
+ @docDragLeave(e)
197
+ return if !@isValidFileDrag(e)
198
+
199
+ @options.onLeave(e)
200
+
201
+ relatedTarget = document.elementFromPoint(e.clientX, e.clientY)
202
+ # do not fire when moving a mouse over a descendant
203
+ return if $.contains(this, relatedTarget)
204
+
205
+ @options.onLeaveNotDescendants(e)
206
+
207
+ @$element.on 'drop', (e) =>
208
+ @docDragLeave(e)
209
+ if !@isOrSetDropDisabled()
210
+ return if !@isValidFileDrag(e)
211
+ e.preventDefault()
212
+ @options.onDrop(e)
213
+ false
214
+
215
+ dropDisabled: (isDisabled) -> @isOrSetDropDisabled(isDisabled)
@@ -0,0 +1,101 @@
1
+ utils = @AnjLab.Uploads.Utils
2
+
3
+ class @AnjLab.Uploads.UploadHandler
4
+ constructor: (options)->
5
+ @options = options
6
+ @queue = []
7
+ @log = options.log
8
+
9
+ @create: (options) ->
10
+ opts = $.extend(true, {}, $.fn.uploadHandlerDefaults, options)
11
+ if utils.isXhrUploadSupported()
12
+ new AnjLab.Uploads.UploadHandlerXhr(opts)
13
+ else
14
+ new AnjLab.Uploads.UploadHandlerForm(opts)
15
+
16
+ # Removes element from queue, starts upload of next
17
+ dequeue: (id) ->
18
+ i = $.inArray(id, @queue)
19
+ max = @options.maxConnections
20
+
21
+ @queue.splice(i, 1)
22
+
23
+ if @queue.length >= max && i < max
24
+ nextId = @queue[max-1]
25
+ @uploadFile(nextId)
26
+
27
+ upload: (id) ->
28
+ # if too many active uploads, wait...
29
+ @uploadFile(id) if @queue.push(id) <= @options.maxConnections
30
+
31
+ retry: (id) ->
32
+ if $.inArray(id, @queue) >= 0
33
+ @uploadFile(id, true)
34
+ else
35
+ @upload(id)
36
+
37
+ cancel: (id) ->
38
+ @log("Cancelling #{id}")
39
+ @options.paramsStore.remove(id)
40
+ @cancelFile(id)
41
+ @dequeue(id)
42
+
43
+ cancelAll: ->
44
+ for fileId in @queue
45
+ @cancel(fileId)
46
+
47
+ @queue = []
48
+
49
+ getQueue: -> @queue
50
+
51
+ reset: ->
52
+ @log('Resetting upload handler')
53
+ @queue = []
54
+ # all handers should call super in their resets
55
+
56
+ uploadComplete: (id) -> @dequeue(id)
57
+
58
+ # protocol for handlers to implement
59
+
60
+ add: (file) -> @log('Not implemented')
61
+ uploadFile: (id, m) -> @log('Not implemented')
62
+ cancelFile: (id) -> @log('Not implemented')
63
+ getName: (id) -> @log('Not implemented')
64
+ getUuid: (id) -> @log('Not implemented')
65
+ isValid: (id) -> @log('Not implemented')
66
+ getSize: (id) -> null
67
+ getFile: (id) -> null
68
+ getResumableFilesData: -> []
69
+
70
+ $.fn.uploadHandlerDefaults =
71
+ debug: false
72
+ forceMultipart: true
73
+ paramsStore: {}
74
+ endpointStore: {}
75
+ maxConnections: 3 # maximum number of concurrent uploads
76
+ uuidParamName: 'qquuid'
77
+ totalFileSizeParamName: 'qqtotalfilesize'
78
+ chunking:
79
+ enabled: false
80
+ partSize: 2000000 # bytes
81
+ paramNames:
82
+ partIndex: 'qqpartindex'
83
+ partByteOffset: 'qqpartbyteoffset'
84
+ chunkSize: 'qqchunksize'
85
+ totalParts: 'qqtotalparts'
86
+ filename: 'qqfilename'
87
+ resume:
88
+ enabled: false
89
+ id: null
90
+ cookiesExpireIn: 7 #days
91
+ paramNames:
92
+ resuming: "qqresume"
93
+
94
+ log: (str, level) -> null
95
+ onProgress: (id, fileName, loaded, total) -> null
96
+ onComplete: (id, fileName, response, xhr) -> null
97
+ onCancel: (id, fileName) -> null
98
+ onUpload: (id, fileName) -> null
99
+ onUploadChunk: (id, fileName, chunkData) -> null
100
+ onAutoRetry: (id, fileName, response, xhr) -> null
101
+ onResume: (id, fileName, chunkData) -> null