fine_uploader 3.1.1 → 3.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE.txt CHANGED
@@ -1,5 +1,3 @@
1
- Copyright (c) 2012 Alif Rachmawadi
2
-
3
1
  MIT License
4
2
 
5
3
  Permission is hereby granted, free of charge, to any person obtaining
@@ -19,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
17
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
18
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
19
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Vendorfile CHANGED
@@ -1,16 +1,27 @@
1
- from 'git://github.com/valums/file-uploader.git', ref: 'be738538a57633e355529ec13c63a7b2493b7ec8' do
1
+ from 'git://github.com/Widen/fine-uploader.git', tag: '3.4.1' do
2
+ # images
2
3
  file 'vendor/assets/images/fine_uploader/loading.gif', 'client/loading.gif'
3
4
  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'
5
+
6
+ # javascripts
7
+ file 'vendor/assets/javascripts/fine_uploader/ajax.requester.js', 'client/js/ajax.requester.js'
6
8
  file 'vendor/assets/javascripts/fine_uploader/button.js', 'client/js/button.js'
9
+ file 'vendor/assets/javascripts/fine_uploader/deletefile.ajax.requester.js', 'client/js/deletefile.ajax.requester.js'
10
+ file 'vendor/assets/javascripts/fine_uploader/dnd.js', 'client/js/dnd.js'
7
11
  file 'vendor/assets/javascripts/fine_uploader/handler.base.js', 'client/js/handler.base.js'
8
12
  file 'vendor/assets/javascripts/fine_uploader/handler.form.js', 'client/js/handler.form.js'
9
13
  file 'vendor/assets/javascripts/fine_uploader/handler.xhr.js', 'client/js/handler.xhr.js'
14
+ file 'vendor/assets/javascripts/fine_uploader/header.js', 'client/js/header.js'
15
+ file 'vendor/assets/javascripts/fine_uploader/iframe.xss.response.js', 'client/js/iframe.xss.response.js'
16
+ file 'vendor/assets/javascripts/fine_uploader/jquery-plugin.js', 'client/js/jquery-plugin.js'
17
+ file 'vendor/assets/javascripts/fine_uploader/paste.js', 'client/js/paste.js'
18
+ file 'vendor/assets/javascripts/fine_uploader/promise.js', 'client/js/promise.js'
10
19
  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
20
  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'
21
+ file 'vendor/assets/javascripts/fine_uploader/util.js', 'client/js/util.js'
22
+ file 'vendor/assets/javascripts/fine_uploader/window.receive.message.js', 'client/js/window.receive.message.js'
23
+
24
+ # scss
14
25
  file 'vendor/assets/stylesheets/fine_uploader.css.scss', 'client/fineuploader.css' do |path|
15
26
  rewrite(path) do |content|
16
27
  content.gsub!('url', 'image-url')
@@ -1,3 +1,3 @@
1
1
  module FineUploader
2
- VERSION = "3.1.1"
2
+ VERSION = "3.4.1"
3
3
  end
@@ -0,0 +1,184 @@
1
+ /** Generic class for sending non-upload ajax requests and handling the associated responses **/
2
+ //TODO Use XDomainRequest if expectCors = true. Not necessary now since only DELETE requests are sent and XDR doesn't support pre-flighting.
3
+ /*globals qq, XMLHttpRequest*/
4
+ qq.AjaxRequestor = function(o) {
5
+ "use strict";
6
+
7
+ var log, shouldParamsBeInQueryString,
8
+ queue = [],
9
+ requestState = [],
10
+ options = {
11
+ method: 'POST',
12
+ maxConnections: 3,
13
+ customHeaders: {},
14
+ endpointStore: {},
15
+ paramsStore: {},
16
+ successfulResponseCodes: [200],
17
+ demoMode: false,
18
+ cors: {
19
+ expected: false,
20
+ sendCredentials: false
21
+ },
22
+ log: function(str, level) {},
23
+ onSend: function(id) {},
24
+ onComplete: function(id, xhr, isError) {},
25
+ onCancel: function(id) {}
26
+ };
27
+
28
+ qq.extend(options, o);
29
+ log = options.log;
30
+ shouldParamsBeInQueryString = getMethod() === 'GET' || getMethod() === 'DELETE';
31
+
32
+
33
+ /**
34
+ * Removes element from queue, sends next request
35
+ */
36
+ function dequeue(id) {
37
+ var i = qq.indexOf(queue, id),
38
+ max = options.maxConnections,
39
+ nextId;
40
+
41
+ delete requestState[id];
42
+ queue.splice(i, 1);
43
+
44
+ if (queue.length >= max && i < max){
45
+ nextId = queue[max-1];
46
+ sendRequest(nextId);
47
+ }
48
+ }
49
+
50
+ function onComplete(id) {
51
+ var xhr = requestState[id].xhr,
52
+ method = getMethod(),
53
+ isError = false;
54
+
55
+ dequeue(id);
56
+
57
+ if (!isResponseSuccessful(xhr.status)) {
58
+ isError = true;
59
+ log(method + " request for " + id + " has failed - response code " + xhr.status, "error");
60
+ }
61
+
62
+ options.onComplete(id, xhr, isError);
63
+ }
64
+
65
+ function sendRequest(id) {
66
+ var xhr = new XMLHttpRequest(),
67
+ method = getMethod(),
68
+ params = {},
69
+ url;
70
+
71
+ options.onSend(id);
72
+
73
+ if (options.paramsStore.getParams) {
74
+ params = options.paramsStore.getParams(id);
75
+ }
76
+
77
+ url = createUrl(id, params);
78
+
79
+ requestState[id].xhr = xhr;
80
+ xhr.onreadystatechange = getReadyStateChangeHandler(id);
81
+ xhr.open(method, url, true);
82
+
83
+ if (options.cors.expected && options.cors.sendCredentials) {
84
+ xhr.withCredentials = true;
85
+ }
86
+
87
+ setHeaders(id);
88
+
89
+ log('Sending ' + method + " request for " + id);
90
+ if (!shouldParamsBeInQueryString && params) {
91
+ xhr.send(qq.obj2url(params, ""));
92
+ }
93
+ else {
94
+ xhr.send();
95
+ }
96
+ }
97
+
98
+ function createUrl(id, params) {
99
+ var endpoint = options.endpointStore.getEndpoint(id),
100
+ addToPath = requestState[id].addToPath;
101
+
102
+ if (addToPath !== undefined) {
103
+ endpoint += "/" + addToPath;
104
+ }
105
+
106
+ if (shouldParamsBeInQueryString && params) {
107
+ return qq.obj2url(params, endpoint);
108
+ }
109
+ else {
110
+ return endpoint;
111
+ }
112
+ }
113
+
114
+ function getReadyStateChangeHandler(id) {
115
+ var xhr = requestState[id].xhr;
116
+
117
+ return function() {
118
+ if (xhr.readyState === 4) {
119
+ onComplete(id, xhr);
120
+ }
121
+ };
122
+ }
123
+
124
+ function setHeaders(id) {
125
+ var xhr = requestState[id].xhr,
126
+ customHeaders = options.customHeaders;
127
+
128
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
129
+ xhr.setRequestHeader("Cache-Control", "no-cache");
130
+
131
+ qq.each(customHeaders, function(name, val) {
132
+ xhr.setRequestHeader(name, val);
133
+ });
134
+ }
135
+
136
+ function cancelRequest(id) {
137
+ var xhr = requestState[id].xhr,
138
+ method = getMethod();
139
+
140
+ if (xhr) {
141
+ xhr.onreadystatechange = null;
142
+ xhr.abort();
143
+ dequeue(id);
144
+
145
+ log('Cancelled ' + method + " for " + id);
146
+ options.onCancel(id);
147
+
148
+ return true;
149
+ }
150
+
151
+ return false;
152
+ }
153
+
154
+ function isResponseSuccessful(responseCode) {
155
+ return qq.indexOf(options.successfulResponseCodes, responseCode) >= 0;
156
+ }
157
+
158
+ function getMethod() {
159
+ if (options.demoMode) {
160
+ return "GET";
161
+ }
162
+
163
+ return options.method;
164
+ }
165
+
166
+
167
+ return {
168
+ send: function(id, addToPath) {
169
+ requestState[id] = {
170
+ addToPath: addToPath
171
+ };
172
+
173
+ var len = queue.push(id);
174
+
175
+ // if too many active connections, wait...
176
+ if (len <= options.maxConnections){
177
+ sendRequest(id);
178
+ }
179
+ },
180
+ cancel: function(id) {
181
+ return cancelRequest(id);
182
+ }
183
+ };
184
+ };
@@ -1,58 +1,34 @@
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
- };
1
+ /*globals qq*/
2
+ qq.UploadButton = function(o) {
3
+ "use strict";
30
4
 
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
- }
5
+ var input,
6
+ disposeSupport = new qq.DisposeSupport(),
7
+ options = {
8
+ element: null,
9
+ // if set to true adds multiple attribute to file input
10
+ multiple: false,
11
+ acceptFiles: null,
12
+ // name attribute of file input
13
+ name: 'file',
14
+ onChange: function(input) {},
15
+ hoverClass: 'qq-upload-button-hover',
16
+ focusClass: 'qq-upload-button-focus'
17
+ };
41
18
 
42
- qq(this._element).removeClass(this._options.focusClass);
43
- this._input = this._createInput();
44
- },
45
- _createInput: function(){
19
+ function createInput() {
46
20
  var input = document.createElement("input");
47
21
 
48
- if (this._options.multiple){
22
+ if (options.multiple){
49
23
  input.setAttribute("multiple", "multiple");
50
24
  }
51
25
 
52
- if (this._options.acceptFiles) input.setAttribute("accept", this._options.acceptFiles);
26
+ if (options.acceptFiles) {
27
+ input.setAttribute("accept", options.acceptFiles);
28
+ }
53
29
 
54
30
  input.setAttribute("type", "file");
55
- input.setAttribute("name", this._options.name);
31
+ input.setAttribute("name", options.name);
56
32
 
57
33
  qq(input).css({
58
34
  position: 'absolute',
@@ -70,24 +46,23 @@ qq.UploadButton.prototype = {
70
46
  opacity: 0
71
47
  });
72
48
 
73
- this._element.appendChild(input);
49
+ options.element.appendChild(input);
74
50
 
75
- var self = this;
76
- this._disposeSupport.attach(input, 'change', function(){
77
- self._options.onChange(input);
51
+ disposeSupport.attach(input, 'change', function(){
52
+ options.onChange(input);
78
53
  });
79
54
 
80
- this._disposeSupport.attach(input, 'mouseover', function(){
81
- qq(self._element).addClass(self._options.hoverClass);
55
+ disposeSupport.attach(input, 'mouseover', function(){
56
+ qq(options.element).addClass(options.hoverClass);
82
57
  });
83
- this._disposeSupport.attach(input, 'mouseout', function(){
84
- qq(self._element).removeClass(self._options.hoverClass);
58
+ disposeSupport.attach(input, 'mouseout', function(){
59
+ qq(options.element).removeClass(options.hoverClass);
85
60
  });
86
- this._disposeSupport.attach(input, 'focus', function(){
87
- qq(self._element).addClass(self._options.focusClass);
61
+ disposeSupport.attach(input, 'focus', function(){
62
+ qq(options.element).addClass(options.focusClass);
88
63
  });
89
- this._disposeSupport.attach(input, 'blur', function(){
90
- qq(self._element).removeClass(self._options.focusClass);
64
+ disposeSupport.attach(input, 'blur', function(){
65
+ qq(options.element).removeClass(options.focusClass);
91
66
  });
92
67
 
93
68
  // IE and Opera, unfortunately have 2 tab stops on file input
@@ -99,4 +74,33 @@ qq.UploadButton.prototype = {
99
74
 
100
75
  return input;
101
76
  }
77
+
78
+
79
+ qq.extend(options, o);
80
+
81
+ // make button suitable container for input
82
+ qq(options.element).css({
83
+ position: 'relative',
84
+ overflow: 'hidden',
85
+ // Make sure browse button is in the right side
86
+ // in Internet Explorer
87
+ direction: 'ltr'
88
+ });
89
+
90
+ input = createInput();
91
+
92
+ return {
93
+ getInput: function(){
94
+ return input;
95
+ },
96
+
97
+ reset: function(){
98
+ if (input.parentNode){
99
+ qq(input).remove();
100
+ }
101
+
102
+ qq(options.element).removeClass(options.focusClass);
103
+ input = createInput();
104
+ }
105
+ };
102
106
  };
@@ -0,0 +1,44 @@
1
+ /** Generic class for sending non-upload ajax requests and handling the associated responses **/
2
+ /*globals qq, XMLHttpRequest*/
3
+ qq.DeleteFileAjaxRequestor = function(o) {
4
+ "use strict";
5
+
6
+ var requestor,
7
+ options = {
8
+ endpointStore: {},
9
+ maxConnections: 3,
10
+ customHeaders: {},
11
+ paramsStore: {},
12
+ demoMode: false,
13
+ cors: {
14
+ expected: false,
15
+ sendCredentials: false
16
+ },
17
+ log: function(str, level) {},
18
+ onDelete: function(id) {},
19
+ onDeleteComplete: function(id, xhr, isError) {}
20
+ };
21
+
22
+ qq.extend(options, o);
23
+
24
+ requestor = new qq.AjaxRequestor({
25
+ method: 'DELETE',
26
+ endpointStore: options.endpointStore,
27
+ paramsStore: options.paramsStore,
28
+ maxConnections: options.maxConnections,
29
+ customHeaders: options.customHeaders,
30
+ successfulResponseCodes: [200, 202, 204],
31
+ demoMode: options.demoMode,
32
+ log: options.log,
33
+ onSend: options.onDelete,
34
+ onComplete: options.onDeleteComplete
35
+ });
36
+
37
+
38
+ return {
39
+ sendDelete: function(id, uuid) {
40
+ requestor.send(id, uuid);
41
+ options.log("Submitted delete file request for " + id);
42
+ }
43
+ };
44
+ };
@@ -73,7 +73,9 @@ qq.DragAndDrop = function(o) {
73
73
  dz.dropDisabled(true);
74
74
 
75
75
  if (dataTransfer.files.length > 1 && !options.multiple) {
76
+ options.callbacks.dropProcessing(false);
76
77
  options.callbacks.error('tooManyFilesError', "");
78
+ dz.dropDisabled(false);
77
79
  }
78
80
  else {
79
81
  droppedFiles = [];