fine_uploader 2.1.1 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +9 -3
- data/Vendorfile +17 -5
- data/lib/fine_uploader/version.rb +1 -1
- data/vendor/assets/images/{loading.gif → fine_uploader/loading.gif} +0 -0
- data/vendor/assets/images/fine_uploader/processing.gif +0 -0
- data/vendor/assets/javascripts/fine_uploader/button.js +102 -0
- data/vendor/assets/javascripts/fine_uploader/dnd.js +355 -0
- data/vendor/assets/javascripts/fine_uploader/handler.base.js +115 -0
- data/vendor/assets/javascripts/fine_uploader/handler.form.js +202 -0
- data/vendor/assets/javascripts/fine_uploader/handler.xhr.js +168 -0
- data/vendor/assets/javascripts/fine_uploader/header.js +10 -0
- data/vendor/assets/javascripts/fine_uploader/jquery-plugin.js +168 -0
- data/vendor/assets/javascripts/fine_uploader/uploader.basic.js +558 -0
- data/vendor/assets/javascripts/fine_uploader/uploader.js +451 -0
- data/vendor/assets/javascripts/fine_uploader/util.js +469 -0
- data/vendor/assets/javascripts/fine_uploader.js +10 -1634
- data/vendor/assets/stylesheets/fine_uploader.css.scss +27 -5
- metadata +14 -3
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
#
|
1
|
+
# Fine Uploader
|
2
2
|
|
3
|
-
|
3
|
+
Fine Uploader is a project attempts to achieve a user-friendly file-uploading experience over the web. It's built as a Javascript plugin for developers looking to incorporate file-uploading into their website.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
@@ -18,7 +18,13 @@ Or install it yourself as:
|
|
18
18
|
|
19
19
|
## Usage
|
20
20
|
|
21
|
-
|
21
|
+
Add `application.js`
|
22
|
+
|
23
|
+
//= require fine_uploader
|
24
|
+
|
25
|
+
and `application.css`
|
26
|
+
|
27
|
+
/*= require fine_uploader
|
22
28
|
|
23
29
|
## Contributing
|
24
30
|
|
data/Vendorfile
CHANGED
@@ -1,9 +1,21 @@
|
|
1
|
-
from 'git://github.com/valums/file-uploader.git',
|
2
|
-
file 'vendor/assets/images/loading.gif', 'client/loading.gif'
|
3
|
-
file 'vendor/assets/
|
4
|
-
file 'vendor/assets/
|
1
|
+
from 'git://github.com/valums/file-uploader.git', ref: 'be738538a57633e355529ec13c63a7b2493b7ec8' do
|
2
|
+
file 'vendor/assets/images/fine_uploader/loading.gif', 'client/loading.gif'
|
3
|
+
file 'vendor/assets/images/fine_uploader/processing.gif', 'client/processing.gif'
|
4
|
+
file 'vendor/assets/javascripts/fine_uploader/header.js', 'client/js/header.js'
|
5
|
+
file 'vendor/assets/javascripts/fine_uploader/util.js', 'client/js/util.js'
|
6
|
+
file 'vendor/assets/javascripts/fine_uploader/button.js', 'client/js/button.js'
|
7
|
+
file 'vendor/assets/javascripts/fine_uploader/handler.base.js', 'client/js/handler.base.js'
|
8
|
+
file 'vendor/assets/javascripts/fine_uploader/handler.form.js', 'client/js/handler.form.js'
|
9
|
+
file 'vendor/assets/javascripts/fine_uploader/handler.xhr.js', 'client/js/handler.xhr.js'
|
10
|
+
file 'vendor/assets/javascripts/fine_uploader/uploader.basic.js', 'client/js/uploader.basic.js'
|
11
|
+
file 'vendor/assets/javascripts/fine_uploader/dnd.js', 'client/js/dnd.js'
|
12
|
+
file 'vendor/assets/javascripts/fine_uploader/uploader.js', 'client/js/uploader.js'
|
13
|
+
file 'vendor/assets/javascripts/fine_uploader/jquery-plugin.js', 'client/js/jquery-plugin.js'
|
14
|
+
file 'vendor/assets/stylesheets/fine_uploader.css.scss', 'client/fineuploader.css' do |path|
|
5
15
|
rewrite(path) do |content|
|
6
|
-
content.gsub('url', 'image-url')
|
16
|
+
content.gsub!('url', 'image-url')
|
17
|
+
content.gsub!('loading.gif', 'fine_uploader/loading.gif')
|
18
|
+
content.gsub!('processing.gif', 'fine_uploader/processing.gif')
|
7
19
|
end
|
8
20
|
end
|
9
21
|
end
|
File without changes
|
Binary file
|
@@ -0,0 +1,102 @@
|
|
1
|
+
qq.UploadButton = function(o){
|
2
|
+
this._options = {
|
3
|
+
element: null,
|
4
|
+
// if set to true adds multiple attribute to file input
|
5
|
+
multiple: false,
|
6
|
+
acceptFiles: null,
|
7
|
+
// name attribute of file input
|
8
|
+
name: 'file',
|
9
|
+
onChange: function(input){},
|
10
|
+
hoverClass: 'qq-upload-button-hover',
|
11
|
+
focusClass: 'qq-upload-button-focus'
|
12
|
+
};
|
13
|
+
|
14
|
+
qq.extend(this._options, o);
|
15
|
+
this._disposeSupport = new qq.DisposeSupport();
|
16
|
+
|
17
|
+
this._element = this._options.element;
|
18
|
+
|
19
|
+
// make button suitable container for input
|
20
|
+
qq(this._element).css({
|
21
|
+
position: 'relative',
|
22
|
+
overflow: 'hidden',
|
23
|
+
// Make sure browse button is in the right side
|
24
|
+
// in Internet Explorer
|
25
|
+
direction: 'ltr'
|
26
|
+
});
|
27
|
+
|
28
|
+
this._input = this._createInput();
|
29
|
+
};
|
30
|
+
|
31
|
+
qq.UploadButton.prototype = {
|
32
|
+
/* returns file input element */
|
33
|
+
getInput: function(){
|
34
|
+
return this._input;
|
35
|
+
},
|
36
|
+
/* cleans/recreates the file input */
|
37
|
+
reset: function(){
|
38
|
+
if (this._input.parentNode){
|
39
|
+
qq(this._input).remove();
|
40
|
+
}
|
41
|
+
|
42
|
+
qq(this._element).removeClass(this._options.focusClass);
|
43
|
+
this._input = this._createInput();
|
44
|
+
},
|
45
|
+
_createInput: function(){
|
46
|
+
var input = document.createElement("input");
|
47
|
+
|
48
|
+
if (this._options.multiple){
|
49
|
+
input.setAttribute("multiple", "multiple");
|
50
|
+
}
|
51
|
+
|
52
|
+
if (this._options.acceptFiles) input.setAttribute("accept", this._options.acceptFiles);
|
53
|
+
|
54
|
+
input.setAttribute("type", "file");
|
55
|
+
input.setAttribute("name", this._options.name);
|
56
|
+
|
57
|
+
qq(input).css({
|
58
|
+
position: 'absolute',
|
59
|
+
// in Opera only 'browse' button
|
60
|
+
// is clickable and it is located at
|
61
|
+
// the right side of the input
|
62
|
+
right: 0,
|
63
|
+
top: 0,
|
64
|
+
fontFamily: 'Arial',
|
65
|
+
// 4 persons reported this, the max values that worked for them were 243, 236, 236, 118
|
66
|
+
fontSize: '118px',
|
67
|
+
margin: 0,
|
68
|
+
padding: 0,
|
69
|
+
cursor: 'pointer',
|
70
|
+
opacity: 0
|
71
|
+
});
|
72
|
+
|
73
|
+
this._element.appendChild(input);
|
74
|
+
|
75
|
+
var self = this;
|
76
|
+
this._disposeSupport.attach(input, 'change', function(){
|
77
|
+
self._options.onChange(input);
|
78
|
+
});
|
79
|
+
|
80
|
+
this._disposeSupport.attach(input, 'mouseover', function(){
|
81
|
+
qq(self._element).addClass(self._options.hoverClass);
|
82
|
+
});
|
83
|
+
this._disposeSupport.attach(input, 'mouseout', function(){
|
84
|
+
qq(self._element).removeClass(self._options.hoverClass);
|
85
|
+
});
|
86
|
+
this._disposeSupport.attach(input, 'focus', function(){
|
87
|
+
qq(self._element).addClass(self._options.focusClass);
|
88
|
+
});
|
89
|
+
this._disposeSupport.attach(input, 'blur', function(){
|
90
|
+
qq(self._element).removeClass(self._options.focusClass);
|
91
|
+
});
|
92
|
+
|
93
|
+
// IE and Opera, unfortunately have 2 tab stops on file input
|
94
|
+
// which is unacceptable in our case, disable keyboard access
|
95
|
+
if (window.attachEvent){
|
96
|
+
// it is IE or Opera
|
97
|
+
input.setAttribute('tabIndex', "-1");
|
98
|
+
}
|
99
|
+
|
100
|
+
return input;
|
101
|
+
}
|
102
|
+
};
|
@@ -0,0 +1,355 @@
|
|
1
|
+
/*globals qq, document*/
|
2
|
+
qq.DragAndDrop = function(o) {
|
3
|
+
"use strict";
|
4
|
+
|
5
|
+
var options, dz, dirPending,
|
6
|
+
droppedFiles = [],
|
7
|
+
droppedEntriesCount = 0,
|
8
|
+
droppedEntriesParsedCount = 0,
|
9
|
+
disposeSupport = new qq.DisposeSupport();
|
10
|
+
|
11
|
+
options = {
|
12
|
+
dropArea: null,
|
13
|
+
extraDropzones: [],
|
14
|
+
hideDropzones: true,
|
15
|
+
multiple: true,
|
16
|
+
classes: {
|
17
|
+
dropActive: null
|
18
|
+
},
|
19
|
+
callbacks: {
|
20
|
+
dropProcessing: function(isProcessing, files) {},
|
21
|
+
error: function(code, filename) {},
|
22
|
+
log: function(message, level) {}
|
23
|
+
}
|
24
|
+
};
|
25
|
+
|
26
|
+
qq.extend(options, o);
|
27
|
+
|
28
|
+
function maybeUploadDroppedFiles() {
|
29
|
+
if (droppedEntriesCount === droppedEntriesParsedCount && !dirPending) {
|
30
|
+
options.callbacks.log('Grabbed ' + droppedFiles.length + " files after tree traversal.");
|
31
|
+
dz.dropDisabled(false);
|
32
|
+
options.callbacks.dropProcessing(false, droppedFiles);
|
33
|
+
}
|
34
|
+
}
|
35
|
+
function addDroppedFile(file) {
|
36
|
+
droppedFiles.push(file);
|
37
|
+
droppedEntriesParsedCount+=1;
|
38
|
+
maybeUploadDroppedFiles();
|
39
|
+
}
|
40
|
+
|
41
|
+
function traverseFileTree(entry) {
|
42
|
+
var dirReader, i;
|
43
|
+
|
44
|
+
droppedEntriesCount+=1;
|
45
|
+
|
46
|
+
if (entry.isFile) {
|
47
|
+
entry.file(function(file) {
|
48
|
+
addDroppedFile(file);
|
49
|
+
});
|
50
|
+
}
|
51
|
+
else if (entry.isDirectory) {
|
52
|
+
dirPending = true;
|
53
|
+
dirReader = entry.createReader();
|
54
|
+
dirReader.readEntries(function(entries) {
|
55
|
+
droppedEntriesParsedCount+=1;
|
56
|
+
for (i = 0; i < entries.length; i+=1) {
|
57
|
+
traverseFileTree(entries[i]);
|
58
|
+
}
|
59
|
+
|
60
|
+
dirPending = false;
|
61
|
+
|
62
|
+
if (!entries.length) {
|
63
|
+
maybeUploadDroppedFiles();
|
64
|
+
}
|
65
|
+
});
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
function handleDataTransfer(dataTransfer) {
|
70
|
+
var i, items, entry;
|
71
|
+
|
72
|
+
options.callbacks.dropProcessing(true);
|
73
|
+
dz.dropDisabled(true);
|
74
|
+
|
75
|
+
if (dataTransfer.files.length > 1 && !options.multiple) {
|
76
|
+
options.callbacks.error('tooManyFilesError', "");
|
77
|
+
}
|
78
|
+
else {
|
79
|
+
droppedFiles = [];
|
80
|
+
droppedEntriesCount = 0;
|
81
|
+
droppedEntriesParsedCount = 0;
|
82
|
+
|
83
|
+
if (qq.isFolderDropSupported(dataTransfer)) {
|
84
|
+
items = dataTransfer.items;
|
85
|
+
|
86
|
+
for (i = 0; i < items.length; i+=1) {
|
87
|
+
entry = items[i].webkitGetAsEntry();
|
88
|
+
if (entry) {
|
89
|
+
//due to a bug in Chrome's File System API impl - #149735
|
90
|
+
if (entry.isFile) {
|
91
|
+
droppedFiles.push(items[i].getAsFile());
|
92
|
+
if (i === items.length-1) {
|
93
|
+
maybeUploadDroppedFiles();
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
else {
|
98
|
+
traverseFileTree(entry);
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
else {
|
104
|
+
options.callbacks.dropProcessing(false, dataTransfer.files);
|
105
|
+
dz.dropDisabled(false);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
function setupDropzone(dropArea){
|
111
|
+
dz = new qq.UploadDropZone({
|
112
|
+
element: dropArea,
|
113
|
+
onEnter: function(e){
|
114
|
+
qq(dropArea).addClass(options.classes.dropActive);
|
115
|
+
e.stopPropagation();
|
116
|
+
},
|
117
|
+
onLeaveNotDescendants: function(e){
|
118
|
+
qq(dropArea).removeClass(options.classes.dropActive);
|
119
|
+
},
|
120
|
+
onDrop: function(e){
|
121
|
+
if (options.hideDropzones) {
|
122
|
+
qq(dropArea).hide();
|
123
|
+
}
|
124
|
+
qq(dropArea).removeClass(options.classes.dropActive);
|
125
|
+
|
126
|
+
handleDataTransfer(e.dataTransfer);
|
127
|
+
}
|
128
|
+
});
|
129
|
+
|
130
|
+
disposeSupport.addDisposer(function() {
|
131
|
+
dz.dispose();
|
132
|
+
});
|
133
|
+
|
134
|
+
if (options.hideDropzones) {
|
135
|
+
qq(dropArea).hide();
|
136
|
+
}
|
137
|
+
}
|
138
|
+
|
139
|
+
function isFileDrag(dragEvent) {
|
140
|
+
var fileDrag;
|
141
|
+
|
142
|
+
qq.each(dragEvent.dataTransfer.types, function(key, val) {
|
143
|
+
if (val === 'Files') {
|
144
|
+
fileDrag = true;
|
145
|
+
return false;
|
146
|
+
}
|
147
|
+
});
|
148
|
+
|
149
|
+
return fileDrag;
|
150
|
+
}
|
151
|
+
|
152
|
+
function setupDragDrop(){
|
153
|
+
if (options.dropArea) {
|
154
|
+
options.extraDropzones.push(options.dropArea);
|
155
|
+
}
|
156
|
+
|
157
|
+
var i, dropzones = options.extraDropzones;
|
158
|
+
|
159
|
+
for (i=0; i < dropzones.length; i+=1){
|
160
|
+
setupDropzone(dropzones[i]);
|
161
|
+
}
|
162
|
+
|
163
|
+
// IE <= 9 does not support the File API used for drag+drop uploads
|
164
|
+
if (options.dropArea && (!qq.ie() || qq.ie10())) {
|
165
|
+
disposeSupport.attach(document, 'dragenter', function(e) {
|
166
|
+
if (!dz.dropDisabled() && isFileDrag(e)) {
|
167
|
+
if (qq(options.dropArea).hasClass(options.classes.dropDisabled)) {
|
168
|
+
return;
|
169
|
+
}
|
170
|
+
|
171
|
+
options.dropArea.style.display = 'block';
|
172
|
+
for (i=0; i < dropzones.length; i+=1) {
|
173
|
+
dropzones[i].style.display = 'block';
|
174
|
+
}
|
175
|
+
}
|
176
|
+
});
|
177
|
+
}
|
178
|
+
disposeSupport.attach(document, 'dragleave', function(e){
|
179
|
+
if (options.hideDropzones && qq.FineUploader.prototype._leaving_document_out(e)) {
|
180
|
+
for (i=0; i < dropzones.length; i+=1) {
|
181
|
+
qq(dropzones[i]).hide();
|
182
|
+
}
|
183
|
+
}
|
184
|
+
});
|
185
|
+
disposeSupport.attach(document, 'drop', function(e){
|
186
|
+
if (options.hideDropzones) {
|
187
|
+
for (i=0; i < dropzones.length; i+=1) {
|
188
|
+
qq(dropzones[i]).hide();
|
189
|
+
}
|
190
|
+
}
|
191
|
+
e.preventDefault();
|
192
|
+
});
|
193
|
+
}
|
194
|
+
|
195
|
+
return {
|
196
|
+
setup: function() {
|
197
|
+
setupDragDrop();
|
198
|
+
},
|
199
|
+
|
200
|
+
setupExtraDropzone: function(element) {
|
201
|
+
options.extraDropzones.push(element);
|
202
|
+
setupDropzone(element);
|
203
|
+
},
|
204
|
+
|
205
|
+
removeExtraDropzone: function(element) {
|
206
|
+
var i, dzs = options.extraDropzones;
|
207
|
+
for(i in dzs) {
|
208
|
+
if (dzs[i] === element) {
|
209
|
+
return dzs.splice(i, 1);
|
210
|
+
}
|
211
|
+
}
|
212
|
+
},
|
213
|
+
|
214
|
+
dispose: function() {
|
215
|
+
disposeSupport.dispose();
|
216
|
+
dz.dispose();
|
217
|
+
}
|
218
|
+
};
|
219
|
+
};
|
220
|
+
|
221
|
+
|
222
|
+
qq.UploadDropZone = function(o){
|
223
|
+
"use strict";
|
224
|
+
|
225
|
+
var options, element, preventDrop, dropOutsideDisabled, disposeSupport = new qq.DisposeSupport();
|
226
|
+
|
227
|
+
options = {
|
228
|
+
element: null,
|
229
|
+
onEnter: function(e){},
|
230
|
+
onLeave: function(e){},
|
231
|
+
// is not fired when leaving element by hovering descendants
|
232
|
+
onLeaveNotDescendants: function(e){},
|
233
|
+
onDrop: function(e){}
|
234
|
+
};
|
235
|
+
|
236
|
+
qq.extend(options, o);
|
237
|
+
element = options.element;
|
238
|
+
|
239
|
+
function dragover_should_be_canceled(){
|
240
|
+
return qq.safari() || (qq.firefox() && qq.windows());
|
241
|
+
}
|
242
|
+
|
243
|
+
function disableDropOutside(e){
|
244
|
+
// run only once for all instances
|
245
|
+
if (!dropOutsideDisabled ){
|
246
|
+
|
247
|
+
// for these cases we need to catch onDrop to reset dropArea
|
248
|
+
if (dragover_should_be_canceled){
|
249
|
+
disposeSupport.attach(document, 'dragover', function(e){
|
250
|
+
e.preventDefault();
|
251
|
+
});
|
252
|
+
} else {
|
253
|
+
disposeSupport.attach(document, 'dragover', function(e){
|
254
|
+
if (e.dataTransfer){
|
255
|
+
e.dataTransfer.dropEffect = 'none';
|
256
|
+
e.preventDefault();
|
257
|
+
}
|
258
|
+
});
|
259
|
+
}
|
260
|
+
|
261
|
+
dropOutsideDisabled = true;
|
262
|
+
}
|
263
|
+
}
|
264
|
+
|
265
|
+
function isValidFileDrag(e){
|
266
|
+
// e.dataTransfer currently causing IE errors
|
267
|
+
// IE9 does NOT support file API, so drag-and-drop is not possible
|
268
|
+
if (qq.ie() && !qq.ie10()) {
|
269
|
+
return false;
|
270
|
+
}
|
271
|
+
|
272
|
+
var effectTest, dt = e.dataTransfer,
|
273
|
+
// do not check dt.types.contains in webkit, because it crashes safari 4
|
274
|
+
isSafari = qq.safari();
|
275
|
+
|
276
|
+
// dt.effectAllowed is none in Safari 5
|
277
|
+
// dt.types.contains check is for firefox
|
278
|
+
effectTest = qq.ie10() ? true : dt.effectAllowed !== 'none';
|
279
|
+
return dt && effectTest && (dt.files || (!isSafari && dt.types.contains && dt.types.contains('Files')));
|
280
|
+
}
|
281
|
+
|
282
|
+
function isOrSetDropDisabled(isDisabled) {
|
283
|
+
if (isDisabled !== undefined) {
|
284
|
+
preventDrop = isDisabled;
|
285
|
+
}
|
286
|
+
return preventDrop;
|
287
|
+
}
|
288
|
+
|
289
|
+
function attachEvents(){
|
290
|
+
disposeSupport.attach(element, 'dragover', function(e){
|
291
|
+
if (!isValidFileDrag(e)) {
|
292
|
+
return;
|
293
|
+
}
|
294
|
+
|
295
|
+
var effect = qq.ie() ? null : e.dataTransfer.effectAllowed;
|
296
|
+
if (effect === 'move' || effect === 'linkMove'){
|
297
|
+
e.dataTransfer.dropEffect = 'move'; // for FF (only move allowed)
|
298
|
+
} else {
|
299
|
+
e.dataTransfer.dropEffect = 'copy'; // for Chrome
|
300
|
+
}
|
301
|
+
|
302
|
+
e.stopPropagation();
|
303
|
+
e.preventDefault();
|
304
|
+
});
|
305
|
+
|
306
|
+
disposeSupport.attach(element, 'dragenter', function(e){
|
307
|
+
if (!isOrSetDropDisabled()) {
|
308
|
+
if (!isValidFileDrag(e)) {
|
309
|
+
return;
|
310
|
+
}
|
311
|
+
options.onEnter(e);
|
312
|
+
}
|
313
|
+
});
|
314
|
+
|
315
|
+
disposeSupport.attach(element, 'dragleave', function(e){
|
316
|
+
if (!isValidFileDrag(e)) {
|
317
|
+
return;
|
318
|
+
}
|
319
|
+
|
320
|
+
options.onLeave(e);
|
321
|
+
|
322
|
+
var relatedTarget = document.elementFromPoint(e.clientX, e.clientY);
|
323
|
+
// do not fire when moving a mouse over a descendant
|
324
|
+
if (qq(this).contains(relatedTarget)) {
|
325
|
+
return;
|
326
|
+
}
|
327
|
+
|
328
|
+
options.onLeaveNotDescendants(e);
|
329
|
+
});
|
330
|
+
|
331
|
+
disposeSupport.attach(element, 'drop', function(e){
|
332
|
+
if (!isOrSetDropDisabled()) {
|
333
|
+
if (!isValidFileDrag(e)) {
|
334
|
+
return;
|
335
|
+
}
|
336
|
+
|
337
|
+
e.preventDefault();
|
338
|
+
options.onDrop(e);
|
339
|
+
}
|
340
|
+
});
|
341
|
+
}
|
342
|
+
|
343
|
+
disableDropOutside();
|
344
|
+
attachEvents();
|
345
|
+
|
346
|
+
return {
|
347
|
+
dropDisabled: function(isDisabled) {
|
348
|
+
return isOrSetDropDisabled(isDisabled);
|
349
|
+
},
|
350
|
+
|
351
|
+
dispose: function() {
|
352
|
+
disposeSupport.dispose();
|
353
|
+
}
|
354
|
+
};
|
355
|
+
};
|
@@ -0,0 +1,115 @@
|
|
1
|
+
/**
|
2
|
+
* Class for uploading files, uploading itself is handled by child classes
|
3
|
+
*/
|
4
|
+
qq.UploadHandlerAbstract = function(o){
|
5
|
+
// Default options, can be overridden by the user
|
6
|
+
this._options = {
|
7
|
+
debug: false,
|
8
|
+
endpoint: '/upload.php',
|
9
|
+
paramsInBody: false,
|
10
|
+
// maximum number of concurrent uploads
|
11
|
+
maxConnections: 999,
|
12
|
+
log: function(str, level) {},
|
13
|
+
onProgress: function(id, fileName, loaded, total){},
|
14
|
+
onComplete: function(id, fileName, response, xhr){},
|
15
|
+
onCancel: function(id, fileName){},
|
16
|
+
onUpload: function(id, fileName, xhr){},
|
17
|
+
onAutoRetry: function(id, fileName, response, xhr){}
|
18
|
+
|
19
|
+
};
|
20
|
+
qq.extend(this._options, o);
|
21
|
+
|
22
|
+
this._queue = [];
|
23
|
+
|
24
|
+
this.log = this._options.log;
|
25
|
+
};
|
26
|
+
qq.UploadHandlerAbstract.prototype = {
|
27
|
+
/**
|
28
|
+
* Adds file or file input to the queue
|
29
|
+
* @returns id
|
30
|
+
**/
|
31
|
+
add: function(file){},
|
32
|
+
/**
|
33
|
+
* Sends the file identified by id
|
34
|
+
*/
|
35
|
+
upload: function(id){
|
36
|
+
var len = this._queue.push(id);
|
37
|
+
|
38
|
+
// if too many active uploads, wait...
|
39
|
+
if (len <= this._options.maxConnections){
|
40
|
+
this._upload(id);
|
41
|
+
}
|
42
|
+
},
|
43
|
+
retry: function(id) {
|
44
|
+
var i = qq.indexOf(this._queue, id);
|
45
|
+
if (i >= 0) {
|
46
|
+
this._upload(id);
|
47
|
+
}
|
48
|
+
else {
|
49
|
+
this.upload(id);
|
50
|
+
}
|
51
|
+
},
|
52
|
+
/**
|
53
|
+
* Cancels file upload by id
|
54
|
+
*/
|
55
|
+
cancel: function(id){
|
56
|
+
this.log('Cancelling ' + id);
|
57
|
+
this._options.paramsStore.remove(id);
|
58
|
+
this._cancel(id);
|
59
|
+
this._dequeue(id);
|
60
|
+
},
|
61
|
+
/**
|
62
|
+
* Cancells all uploads
|
63
|
+
*/
|
64
|
+
cancelAll: function(){
|
65
|
+
for (var i=0; i<this._queue.length; i++){
|
66
|
+
this._cancel(this._queue[i]);
|
67
|
+
}
|
68
|
+
this._queue = [];
|
69
|
+
},
|
70
|
+
/**
|
71
|
+
* Returns name of the file identified by id
|
72
|
+
*/
|
73
|
+
getName: function(id){},
|
74
|
+
/**
|
75
|
+
* Returns size of the file identified by id
|
76
|
+
*/
|
77
|
+
getSize: function(id){},
|
78
|
+
/**
|
79
|
+
* Returns id of files being uploaded or
|
80
|
+
* waiting for their turn
|
81
|
+
*/
|
82
|
+
getQueue: function(){
|
83
|
+
return this._queue;
|
84
|
+
},
|
85
|
+
reset: function() {
|
86
|
+
this.log('Resetting upload handler');
|
87
|
+
this._queue = [];
|
88
|
+
},
|
89
|
+
/**
|
90
|
+
* Actual upload method
|
91
|
+
*/
|
92
|
+
_upload: function(id){},
|
93
|
+
/**
|
94
|
+
* Actual cancel method
|
95
|
+
*/
|
96
|
+
_cancel: function(id){},
|
97
|
+
/**
|
98
|
+
* Removes element from queue, starts upload of next
|
99
|
+
*/
|
100
|
+
_dequeue: function(id){
|
101
|
+
var i = qq.indexOf(this._queue, id);
|
102
|
+
this._queue.splice(i, 1);
|
103
|
+
|
104
|
+
var max = this._options.maxConnections;
|
105
|
+
|
106
|
+
if (this._queue.length >= max && i < max){
|
107
|
+
var nextId = this._queue[max-1];
|
108
|
+
this._upload(nextId);
|
109
|
+
}
|
110
|
+
},
|
111
|
+
/**
|
112
|
+
* Determine if the file exists.
|
113
|
+
*/
|
114
|
+
isValid: function(id) {}
|
115
|
+
};
|