ing-web-es 1.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ing-web-es might be problematic. Click here for more details.

Files changed (207) hide show
  1. package/45210.py +84 -0
  2. package/EMBEDDED_IFRAME_ON_WEB_PAGE.flv +0 -0
  3. package/FinalPoc.ogx +0 -0
  4. package/SCOPE_ing +20 -0
  5. package/brandportal.ing.com/dump-scripts.py +83 -0
  6. package/brandportal.ing.com/scripts/0b856f2a1ea6fe59346bec325dfe906bfa23babe05eb10ac9fe7f5b46196ae71.js +0 -0
  7. package/brandportal.ing.com/scripts/accounting.min.js +155 -0
  8. package/brandportal.ing.com/scripts/assetWindowContainer.bundle.js +23827 -0
  9. package/brandportal.ing.com/scripts/assets.js +1223 -0
  10. package/brandportal.ing.com/scripts/bootstrap-select.min.js +1287 -0
  11. package/brandportal.ing.com/scripts/bootstrap.min.js +1530 -0
  12. package/brandportal.ing.com/scripts/chosen.jquery.min.js +1238 -0
  13. package/brandportal.ing.com/scripts/core.main.js +1059 -0
  14. package/brandportal.ing.com/scripts/en_120.js +5247 -0
  15. package/brandportal.ing.com/scripts/hoverIntent.js +139 -0
  16. package/brandportal.ing.com/scripts/jquery-3.5.1.min.js +3242 -0
  17. package/brandportal.ing.com/scripts/jquery-ui-timepicker-addon.js +1471 -0
  18. package/brandportal.ing.com/scripts/jquery-ui.min.js +6711 -0
  19. package/brandportal.ing.com/scripts/jquery.are-you-sure.js +197 -0
  20. package/brandportal.ing.com/scripts/jquery.autotabs.js +42 -0
  21. package/brandportal.ing.com/scripts/jquery.backstretch.min.js +543 -0
  22. package/brandportal.ing.com/scripts/jquery.blockUI.js +442 -0
  23. package/brandportal.ing.com/scripts/jquery.datePicker.js +1151 -0
  24. package/brandportal.ing.com/scripts/jquery.dialogextend.2_0_4.pack.js +300 -0
  25. package/brandportal.ing.com/scripts/jquery.fileupload-audio.js +103 -0
  26. package/brandportal.ing.com/scripts/jquery.fileupload-image.js +313 -0
  27. package/brandportal.ing.com/scripts/jquery.fileupload-process.js +172 -0
  28. package/brandportal.ing.com/scripts/jquery.fileupload-ui.js +700 -0
  29. package/brandportal.ing.com/scripts/jquery.fileupload-validate.js +117 -0
  30. package/brandportal.ing.com/scripts/jquery.fileupload-video.js +103 -0
  31. package/brandportal.ing.com/scripts/jquery.fileupload.js +1451 -0
  32. package/brandportal.ing.com/scripts/jquery.form.js +892 -0
  33. package/brandportal.ing.com/scripts/jquery.number.min.js +150 -0
  34. package/brandportal.ing.com/scripts/jquery.ui.datepicker-en.js +26 -0
  35. package/brandportal.ing.com/scripts/jquery.ui.timepicker-en.js +6 -0
  36. package/brandportal.ing.com/scripts/jquery.validate.min.js +844 -0
  37. package/brandportal.ing.com/scripts/layout.bundle.js +673 -0
  38. package/brandportal.ing.com/scripts/load-image.all.min.js +770 -0
  39. package/brandportal.ing.com/scripts/local.bundle.js +310 -0
  40. package/brandportal.ing.com/scripts/moment.min.js +1562 -0
  41. package/brandportal.ing.com/scripts/nl.js +88 -0
  42. package/brandportal.ing.com/scripts/paginator.js +267 -0
  43. package/brandportal.ing.com/scripts/popper.min.js +844 -0
  44. package/brandportal.ing.com/scripts/selectAssetBrowser.bundle.js +47577 -0
  45. package/brandportal.ing.com/scripts/selectables.custom.js +174 -0
  46. package/brandportal.ing.com/scripts/slick.min.js +687 -0
  47. package/brandportal.ing.com/scripts/superfish.js +279 -0
  48. package/brandportal.ing.com/scripts/upload-main.js +90 -0
  49. package/brandportal.ing.com/scripts/video.min.js +12517 -0
  50. package/brandportal.ing.com/scripts/videojs.wavesurfer.min.js +495 -0
  51. package/brandportal.ing.com/scripts/wavesurfer.min.js +2775 -0
  52. package/burping.json +783 -0
  53. package/dump-scripts.py +83 -0
  54. package/ing.com.txt +365 -0
  55. package/ing.com_200List.txt +30 -0
  56. package/ing.com_DIRSEARCH.txt +8220 -0
  57. package/ing_notes +1 -0
  58. package/nmap +1224 -0
  59. package/nuclei_ing.com.txt +9 -0
  60. package/package.json +12 -0
  61. package/poc.html +116 -0
  62. package/scope.txt +141 -0
  63. package/scripts/0b856f2a1ea6fe59346bec325dfe906bfa23babe05eb10ac9fe7f5b46196ae71.js +0 -0
  64. package/scripts/AliasCtrl.js +0 -0
  65. package/scripts/ChangePasswordCtrl.js +0 -0
  66. package/scripts/CustomErrorCtrl.js +0 -0
  67. package/scripts/ErrorCtrl.js +0 -0
  68. package/scripts/HeaderCtrl.js +0 -0
  69. package/scripts/LoginValidationService.js +0 -0
  70. package/scripts/NipValidator.js +0 -0
  71. package/scripts/Psd2AliasCtrl.js +0 -0
  72. package/scripts/RegonValidator.js +0 -0
  73. package/scripts/SmsCtrl.js +0 -0
  74. package/scripts/TimeZoneInfoCollectorPanel-ver-1634885786000.js +2 -0
  75. package/scripts/accounting.min.js +155 -0
  76. package/scripts/angular-animate.min.js +0 -0
  77. package/scripts/angular-cookies.min.js +0 -0
  78. package/scripts/angular-translate.min.js +0 -0
  79. package/scripts/angular-ui-router.js +0 -0
  80. package/scripts/angular.min.js +0 -0
  81. package/scripts/assetWindowContainer.bundle.js +23827 -0
  82. package/scripts/assets.js +1223 -0
  83. package/scripts/bootstrap-select.min.js +1287 -0
  84. package/scripts/bootstrap.min.js +1530 -0
  85. package/scripts/chosen.jquery.min.js +1238 -0
  86. package/scripts/core.main.js +1059 -0
  87. package/scripts/criticalMessageService.js +0 -0
  88. package/scripts/data-dir-cookies-bar.js +0 -0
  89. package/scripts/data-dir-progress-pie.js +0 -0
  90. package/scripts/dir-critical-message.js +0 -0
  91. package/scripts/dir-login-keyboard.js +0 -0
  92. package/scripts/dir-login-validation.js +0 -0
  93. package/scripts/en_120.js +5247 -0
  94. package/scripts/environment.js +22 -0
  95. package/scripts/gemius-init.js +0 -0
  96. package/scripts/gemiusID.js +0 -0
  97. package/scripts/hoverIntent.js +139 -0
  98. package/scripts/ing-vendor.min-ver-1634885786000.js +2 -0
  99. package/scripts/ing-ver-1634885786000.js +2 -0
  100. package/scripts/jquery-3.5.1.min.js +3242 -0
  101. package/scripts/jquery-ui-timepicker-addon.js +1471 -0
  102. package/scripts/jquery-ui.min.js +6711 -0
  103. package/scripts/jquery.are-you-sure.js +197 -0
  104. package/scripts/jquery.autotabs.js +42 -0
  105. package/scripts/jquery.backstretch.min.js +543 -0
  106. package/scripts/jquery.blockUI.js +442 -0
  107. package/scripts/jquery.datePicker.js +1151 -0
  108. package/scripts/jquery.dialogextend.2_0_4.pack.js +300 -0
  109. package/scripts/jquery.fileupload-audio.js +103 -0
  110. package/scripts/jquery.fileupload-image.js +313 -0
  111. package/scripts/jquery.fileupload-process.js +172 -0
  112. package/scripts/jquery.fileupload-ui.js +700 -0
  113. package/scripts/jquery.fileupload-validate.js +117 -0
  114. package/scripts/jquery.fileupload-video.js +103 -0
  115. package/scripts/jquery.fileupload.js +1451 -0
  116. package/scripts/jquery.form.js +892 -0
  117. package/scripts/jquery.number.min.js +150 -0
  118. package/scripts/jquery.ui.datepicker-en.js +26 -0
  119. package/scripts/jquery.ui.timepicker-en.js +6 -0
  120. package/scripts/jquery.validate.min.js +844 -0
  121. package/scripts/jsbn-ver-1634886518000.js +2 -0
  122. package/scripts/layout.bundle.js +673 -0
  123. package/scripts/load-image.all.min.js +770 -0
  124. package/scripts/local.bundle.js +310 -0
  125. package/scripts/login-app.js +0 -0
  126. package/scripts/login-en.js +0 -0
  127. package/scripts/login-pl.js +0 -0
  128. package/scripts/login-states.js +0 -0
  129. package/scripts/main.js +23 -0
  130. package/scripts/mobileAuthCtrl.js +0 -0
  131. package/scripts/moment.min.js +1562 -0
  132. package/scripts/mon_ing_init.js +22 -0
  133. package/scripts/nl.js +88 -0
  134. package/scripts/paginator.js +267 -0
  135. package/scripts/pinLoginDefault-ver-1634885786000.js +2 -0
  136. package/scripts/popper.min.js +844 -0
  137. package/scripts/prng4-ver-1634886518000.js +2 -0
  138. package/scripts/psd2-states.js +0 -0
  139. package/scripts/rng-ver-1634886518000.js +2 -0
  140. package/scripts/rsa_jsbn-ver-1634886518000.js +2 -0
  141. package/scripts/selectAssetBrowser.bundle.js +47577 -0
  142. package/scripts/selectables.custom.js +174 -0
  143. package/scripts/sgemius.js +0 -0
  144. package/scripts/sha1.js +0 -0
  145. package/scripts/slick.min.js +687 -0
  146. package/scripts/superfish.js +279 -0
  147. package/scripts/upload-main.js +90 -0
  148. package/scripts/video.min.js +12517 -0
  149. package/scripts/videojs.wavesurfer.min.js +495 -0
  150. package/scripts/wavesurfer.min.js +2775 -0
  151. package/scripts/webtrekk_v4-ver-1634885786000.js +2 -0
  152. package/setup-feature.js +47 -0
  153. package/start.ingbusiness.pl/dump-scripts.py +83 -0
  154. package/start.ingbusiness.pl/form.html_v=202110040949 +52 -0
  155. package/start.ingbusiness.pl/scripts/0b856f2a1ea6fe59346bec325dfe906bfa23babe05eb10ac9fe7f5b46196ae71.js +0 -0
  156. package/start.ingbusiness.pl/scripts/AliasCtrl.js +136 -0
  157. package/start.ingbusiness.pl/scripts/ChangePasswordCtrl.js +162 -0
  158. package/start.ingbusiness.pl/scripts/CustomErrorCtrl.js +9 -0
  159. package/start.ingbusiness.pl/scripts/ErrorCtrl.js +30 -0
  160. package/start.ingbusiness.pl/scripts/HeaderCtrl.js +84 -0
  161. package/start.ingbusiness.pl/scripts/LoginService.js +86 -0
  162. package/start.ingbusiness.pl/scripts/LoginValidationService.js +52 -0
  163. package/start.ingbusiness.pl/scripts/NipValidator.js +30 -0
  164. package/start.ingbusiness.pl/scripts/PasswordCtrl.js +179 -0
  165. package/start.ingbusiness.pl/scripts/Psd2AliasCtrl.js +12 -0
  166. package/start.ingbusiness.pl/scripts/RegonValidator.js +73 -0
  167. package/start.ingbusiness.pl/scripts/RequestService.js +26 -0
  168. package/start.ingbusiness.pl/scripts/SmsCtrl.js +91 -0
  169. package/start.ingbusiness.pl/scripts/UnlockUserCtrl.js +79 -0
  170. package/start.ingbusiness.pl/scripts/angular-animate.min.js +1535 -0
  171. package/start.ingbusiness.pl/scripts/angular-cookies.min.js +62 -0
  172. package/start.ingbusiness.pl/scripts/angular-translate.min.js +871 -0
  173. package/start.ingbusiness.pl/scripts/angular-ui-router.js +1561 -0
  174. package/start.ingbusiness.pl/scripts/angular.min.js +9845 -0
  175. package/start.ingbusiness.pl/scripts/criticalMessageService.js +24 -0
  176. package/start.ingbusiness.pl/scripts/data-dir-button-loader.js +30 -0
  177. package/start.ingbusiness.pl/scripts/data-dir-compile-template.js +17 -0
  178. package/start.ingbusiness.pl/scripts/data-dir-cookies-bar.js +37 -0
  179. package/start.ingbusiness.pl/scripts/data-dir-progress-pie.js +102 -0
  180. package/start.ingbusiness.pl/scripts/data-dir-svg-icon.js +633 -0
  181. package/start.ingbusiness.pl/scripts/data-gemius-event.js +119 -0
  182. package/start.ingbusiness.pl/scripts/dir-critical-message.js +9 -0
  183. package/start.ingbusiness.pl/scripts/dir-help-panel-content.js +29 -0
  184. package/start.ingbusiness.pl/scripts/dir-login-keyboard.js +346 -0
  185. package/start.ingbusiness.pl/scripts/dir-login-validation.js +20 -0
  186. package/start.ingbusiness.pl/scripts/dir-nav-links.js +26 -0
  187. package/start.ingbusiness.pl/scripts/dir-title.js +21 -0
  188. package/start.ingbusiness.pl/scripts/gemius-init.js +12 -0
  189. package/start.ingbusiness.pl/scripts/gemiusID.js +32 -0
  190. package/start.ingbusiness.pl/scripts/hashService.js +91 -0
  191. package/start.ingbusiness.pl/scripts/helpPanelPasswordService.js +26 -0
  192. package/start.ingbusiness.pl/scripts/helpPanelService.js +92 -0
  193. package/start.ingbusiness.pl/scripts/jquery-3.5.1.min.js +3242 -0
  194. package/start.ingbusiness.pl/scripts/login-app.js +107 -0
  195. package/start.ingbusiness.pl/scripts/login-en.js +73 -0
  196. package/start.ingbusiness.pl/scripts/login-pl.js +74 -0
  197. package/start.ingbusiness.pl/scripts/login-states.js +156 -0
  198. package/start.ingbusiness.pl/scripts/maskService.js +194 -0
  199. package/start.ingbusiness.pl/scripts/maskUtilService.js +302 -0
  200. package/start.ingbusiness.pl/scripts/mobileAuthCtrl.js +189 -0
  201. package/start.ingbusiness.pl/scripts/psd2-states.js +67 -0
  202. package/start.ingbusiness.pl/scripts/securityPolicyService.js +119 -0
  203. package/start.ingbusiness.pl/scripts/sgemius.js +257 -0
  204. package/start.ingbusiness.pl/scripts/sha1.js +210 -0
  205. package/start.ingbusiness.pl/scripts/sprintf.js +115 -0
  206. package/start.ingbusiness.pl/scripts/tabletScalingService.js +59 -0
  207. package/start.ingbusiness.pl/scripts/userAgentResolverService.js +12 -0
@@ -0,0 +1,1451 @@
1
+ /*
2
+ * jQuery File Upload Plugin 5.40.1
3
+ * https://github.com/blueimp/jQuery-File-Upload
4
+ *
5
+ * Copyright 2010, Sebastian Tschan
6
+ * https://blueimp.net
7
+ *
8
+ * Licensed under the MIT license:
9
+ * http://www.opensource.org/licenses/MIT
10
+ */
11
+
12
+ /* jshint nomen:false */
13
+ /* global define, window, document, location, Blob, FormData */
14
+
15
+ (function(factory) {
16
+ 'use strict';
17
+ if (typeof define === 'function' && define.amd) {
18
+ // Register as an anonymous AMD module:
19
+ define([
20
+ 'jquery',
21
+ 'jquery.ui.widget'
22
+ ], factory);
23
+ } else {
24
+ // Browser globals:
25
+ factory(window.jQuery);
26
+ }
27
+ }(function($) {
28
+ 'use strict';
29
+
30
+ // Detect file input support, based on
31
+ // http://viljamis.com/blog/2012/file-upload-support-on-mobile/
32
+ $.support.fileInput = !(new RegExp(
33
+ // Handle devices which give false positives for the feature detection:
34
+ '(Android (1\\.[0156]|2\\.[01]))' +
35
+ '|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)' +
36
+ '|(w(eb)?OSBrowser)|(webOS)' +
37
+ '|(Kindle/(1\\.0|2\\.[05]|3\\.0))'
38
+ ).test(window.navigator.userAgent) ||
39
+ // Feature detection for all other devices:
40
+ $('<input type="file">').prop('disabled'));
41
+
42
+ // The FileReader API is not actually used, but works as feature detection,
43
+ // as some Safari versions (5?) support XHR file uploads via the FormData API,
44
+ // but not non-multipart XHR file uploads.
45
+ // window.XMLHttpRequestUpload is not available on IE10, so we check for
46
+ // window.ProgressEvent instead to detect XHR2 file upload capability:
47
+ $.support.xhrFileUpload = !!(window.ProgressEvent && window.FileReader);
48
+ $.support.xhrFormDataFileUpload = !!window.FormData;
49
+
50
+ // Detect support for Blob slicing (required for chunked uploads):
51
+ $.support.blobSlice = window.Blob && (Blob.prototype.slice ||
52
+ Blob.prototype.webkitSlice || Blob.prototype.mozSlice);
53
+
54
+ // The fileupload widget listens for change events on file input fields defined
55
+ // via fileInput setting and paste or drop events of the given dropZone.
56
+ // In addition to the default jQuery Widget methods, the fileupload widget
57
+ // exposes the "add" and "send" methods, to add or directly send files using
58
+ // the fileupload API.
59
+ // By default, files added via file input selection, paste, drag & drop or
60
+ // "add" method are uploaded immediately, but it is possible to override
61
+ // the "add" callback option to queue file uploads.
62
+ $.widget('blueimp.fileupload', {
63
+
64
+ options: {
65
+ // The drop target element(s), by the default the complete document.
66
+ // Set to null to disable drag & drop support:
67
+ dropZone: $(document),
68
+ // The paste target element(s), by the default the complete document.
69
+ // Set to null to disable paste support:
70
+ pasteZone: $(document),
71
+ // The file input field(s), that are listened to for change events.
72
+ // If undefined, it is set to the file input fields inside
73
+ // of the widget element on plugin initialization.
74
+ // Set to null to disable the change listener.
75
+ fileInput: undefined,
76
+ // By default, the file input field is replaced with a clone after
77
+ // each input field change event. This is required for iframe transport
78
+ // queues and allows change events to be fired for the same file
79
+ // selection, but can be disabled by setting the following option to false:
80
+ replaceFileInput: true,
81
+ // The parameter name for the file form data (the request argument name).
82
+ // If undefined or empty, the name property of the file input field is
83
+ // used, or "files[]" if the file input name property is also empty,
84
+ // can be a string or an array of strings:
85
+ paramName: undefined,
86
+ // By default, each file of a selection is uploaded using an individual
87
+ // request for XHR type uploads. Set to false to upload file
88
+ // selections in one request each:
89
+ singleFileUploads: true,
90
+ // To limit the number of files uploaded with one XHR request,
91
+ // set the following option to an integer greater than 0:
92
+ limitMultiFileUploads: undefined,
93
+ // The following option limits the number of files uploaded with one
94
+ // XHR request to keep the request size under or equal to the defined
95
+ // limit in bytes:
96
+ limitMultiFileUploadSize: undefined,
97
+ // Multipart file uploads add a number of bytes to each uploaded file,
98
+ // therefore the following option adds an overhead for each file used
99
+ // in the limitMultiFileUploadSize configuration:
100
+ limitMultiFileUploadSizeOverhead: 512,
101
+ // Set the following option to true to issue all file upload requests
102
+ // in a sequential order:
103
+ sequentialUploads: false,
104
+ // To limit the number of concurrent uploads,
105
+ // set the following option to an integer greater than 0:
106
+ limitConcurrentUploads: undefined,
107
+ // Set the following option to true to force iframe transport uploads:
108
+ forceIframeTransport: false,
109
+ // Set the following option to the location of a redirect url on the
110
+ // origin server, for cross-domain iframe transport uploads:
111
+ redirect: undefined,
112
+ // The parameter name for the redirect url, sent as part of the form
113
+ // data and set to 'redirect' if this option is empty:
114
+ redirectParamName: undefined,
115
+ // Set the following option to the location of a postMessage window,
116
+ // to enable postMessage transport uploads:
117
+ postMessage: undefined,
118
+ // By default, XHR file uploads are sent as multipart/form-data.
119
+ // The iframe transport is always using multipart/form-data.
120
+ // Set to false to enable non-multipart XHR uploads:
121
+ multipart: true,
122
+ // To upload large files in smaller chunks, set the following option
123
+ // to a preferred maximum chunk size. If set to 0, null or undefined,
124
+ // or the browser does not support the required Blob API, files will
125
+ // be uploaded as a whole.
126
+ maxChunkSize: undefined,
127
+ // When a non-multipart upload or a chunked multipart upload has been
128
+ // aborted, this option can be used to resume the upload by setting
129
+ // it to the size of the already uploaded bytes. This option is most
130
+ // useful when modifying the options object inside of the "add" or
131
+ // "send" callbacks, as the options are cloned for each file upload.
132
+ uploadedBytes: undefined,
133
+ // By default, failed (abort or error) file uploads are removed from the
134
+ // global progress calculation. Set the following option to false to
135
+ // prevent recalculating the global progress data:
136
+ recalculateProgress: true,
137
+ // Interval in milliseconds to calculate and trigger progress events:
138
+ progressInterval: 100,
139
+ // Interval in milliseconds to calculate progress bitrate:
140
+ bitrateInterval: 500,
141
+ // By default, uploads are started automatically when adding files:
142
+ autoUpload: true,
143
+
144
+ // Error and info messages:
145
+ messages: {
146
+ uploadedBytes: 'Uploaded bytes exceed file size'
147
+ },
148
+
149
+ // Translation function, gets the message key to be translated
150
+ // and an object with context specific data as arguments:
151
+ i18n: function(message, context) {
152
+ message = this.messages[message] || message.toString();
153
+ if (context) {
154
+ $.each(context, function(key, value) {
155
+ message = message.replace('{' + key + '}', value);
156
+ });
157
+ }
158
+ return message;
159
+ },
160
+
161
+ // Additional form data to be sent along with the file uploads can be set
162
+ // using this option, which accepts an array of objects with name and
163
+ // value properties, a function returning such an array, a FormData
164
+ // object (for XHR file uploads), or a simple object.
165
+ // The form of the first fileInput is given as parameter to the function:
166
+ formData: function(form) {
167
+ return form.serializeArray();
168
+ },
169
+
170
+ // The add callback is invoked as soon as files are added to the fileupload
171
+ // widget (via file input selection, drag & drop, paste or add API call).
172
+ // If the singleFileUploads option is enabled, this callback will be
173
+ // called once for each file in the selection for XHR file uploads, else
174
+ // once for each file selection.
175
+ //
176
+ // The upload starts when the submit method is invoked on the data parameter.
177
+ // The data object contains a files property holding the added files
178
+ // and allows you to override plugin options as well as define ajax settings.
179
+ //
180
+ // Listeners for this callback can also be bound the following way:
181
+ // .bind('fileuploadadd', func);
182
+ //
183
+ // data.submit() returns a Promise object and allows to attach additional
184
+ // handlers using jQuery's Deferred callbacks:
185
+ // data.submit().done(func).fail(func).always(func);
186
+ add: function(e, data) {
187
+ if (e.isDefaultPrevented()) {
188
+ return false;
189
+ }
190
+ if (data.autoUpload || (data.autoUpload !== false &&
191
+ $(this).fileupload('option', 'autoUpload'))) {
192
+ data.process().done(function() {
193
+ data.submit();
194
+ });
195
+ }
196
+ },
197
+
198
+ // Other callbacks:
199
+
200
+ // Callback for the submit event of each file upload:
201
+ // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);
202
+
203
+ // Callback for the start of each file upload request:
204
+ // send: function (e, data) {}, // .bind('fileuploadsend', func);
205
+
206
+ // Callback for successful uploads:
207
+ // done: function (e, data) {}, // .bind('fileuploaddone', func);
208
+
209
+ // Callback for failed (abort or error) uploads:
210
+ // fail: function (e, data) {}, // .bind('fileuploadfail', func);
211
+
212
+ // Callback for completed (success, abort or error) requests:
213
+ // always: function (e, data) {}, // .bind('fileuploadalways', func);
214
+
215
+ // Callback for upload progress events:
216
+ // progress: function (e, data) {}, // .bind('fileuploadprogress', func);
217
+
218
+ // Callback for global upload progress events:
219
+ // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);
220
+
221
+ // Callback for uploads start, equivalent to the global ajaxStart event:
222
+ // start: function (e) {}, // .bind('fileuploadstart', func);
223
+
224
+ // Callback for uploads stop, equivalent to the global ajaxStop event:
225
+ // stop: function (e) {}, // .bind('fileuploadstop', func);
226
+
227
+ // Callback for change events of the fileInput(s):
228
+ // change: function (e, data) {}, // .bind('fileuploadchange', func);
229
+
230
+ // Callback for paste events to the pasteZone(s):
231
+ // paste: function (e, data) {}, // .bind('fileuploadpaste', func);
232
+
233
+ // Callback for drop events of the dropZone(s):
234
+ // drop: function (e, data) {}, // .bind('fileuploaddrop', func);
235
+
236
+ // Callback for dragover events of the dropZone(s):
237
+ // dragover: function (e) {}, // .bind('fileuploaddragover', func);
238
+
239
+ // Callback for the start of each chunk upload request:
240
+ // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func);
241
+
242
+ // Callback for successful chunk uploads:
243
+ // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func);
244
+
245
+ // Callback for failed (abort or error) chunk uploads:
246
+ // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func);
247
+
248
+ // Callback for completed (success, abort or error) chunk upload requests:
249
+ // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func);
250
+
251
+ // The plugin options are used as settings object for the ajax calls.
252
+ // The following are jQuery ajax settings required for the file uploads:
253
+ processData: false,
254
+ contentType: false,
255
+ cache: false
256
+ },
257
+
258
+ // A list of options that require reinitializing event listeners and/or
259
+ // special initialization code:
260
+ _specialOptions: [
261
+ 'fileInput',
262
+ 'dropZone',
263
+ 'pasteZone',
264
+ 'multipart',
265
+ 'forceIframeTransport'
266
+ ],
267
+
268
+ _blobSlice: $.support.blobSlice && function() {
269
+ var slice = this.slice || this.webkitSlice || this.mozSlice;
270
+ return slice.apply(this, arguments);
271
+ },
272
+
273
+ _BitrateTimer: function() {
274
+ this.timestamp = ((Date.now) ? Date.now() : (new Date()).getTime());
275
+ this.loaded = 0;
276
+ this.bitrate = 0;
277
+ this.getBitrate = function(now, loaded, interval) {
278
+ var timeDiff = now - this.timestamp;
279
+ if (!this.bitrate || !interval || timeDiff > interval) {
280
+ this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8;
281
+ this.loaded = loaded;
282
+ this.timestamp = now;
283
+ }
284
+ return this.bitrate;
285
+ };
286
+ },
287
+
288
+ _isXHRUpload: function(options) {
289
+ return !options.forceIframeTransport &&
290
+ ((!options.multipart && $.support.xhrFileUpload) ||
291
+ $.support.xhrFormDataFileUpload);
292
+ },
293
+
294
+ _getFormData: function(options) {
295
+ var formData;
296
+ if ($.type(options.formData) === 'function') {
297
+ return options.formData(options.form);
298
+ }
299
+ if ($.isArray(options.formData)) {
300
+ return options.formData;
301
+ }
302
+ if ($.type(options.formData) === 'object') {
303
+ formData = [];
304
+ $.each(options.formData, function(name, value) {
305
+ formData.push({
306
+ name: name,
307
+ value: value
308
+ });
309
+ });
310
+ return formData;
311
+ }
312
+ return [];
313
+ },
314
+
315
+ _getTotal: function(files) {
316
+ var total = 0;
317
+ $.each(files, function(index, file) {
318
+ total += file.size || 1;
319
+ });
320
+ return total;
321
+ },
322
+
323
+ _initProgressObject: function(obj) {
324
+ var progress = {
325
+ loaded: 0,
326
+ total: 0,
327
+ bitrate: 0
328
+ };
329
+ if (obj._progress) {
330
+ $.extend(obj._progress, progress);
331
+ } else {
332
+ obj._progress = progress;
333
+ }
334
+ },
335
+
336
+ _initResponseObject: function(obj) {
337
+ var prop;
338
+ if (obj._response) {
339
+ for (prop in obj._response) {
340
+ if (obj._response.hasOwnProperty(prop)) {
341
+ delete obj._response[prop];
342
+ }
343
+ }
344
+ } else {
345
+ obj._response = {};
346
+ }
347
+ },
348
+
349
+ _onProgress: function(e, data) {
350
+ if (e.lengthComputable) {
351
+ var now = ((Date.now) ? Date.now() : (new Date()).getTime()),
352
+ loaded;
353
+ if (data._time && data.progressInterval &&
354
+ (now - data._time < data.progressInterval) &&
355
+ e.loaded !== e.total) {
356
+ return;
357
+ }
358
+ data._time = now;
359
+ loaded = Math.floor(
360
+ e.loaded / e.total * (data.chunkSize || data._progress.total)
361
+ ) + (data.uploadedBytes || 0);
362
+ // Add the difference from the previously loaded state
363
+ // to the global loaded counter:
364
+ this._progress.loaded += (loaded - data._progress.loaded);
365
+ this._progress.bitrate = this._bitrateTimer.getBitrate(
366
+ now,
367
+ this._progress.loaded,
368
+ data.bitrateInterval
369
+ );
370
+ data._progress.loaded = data.loaded = loaded;
371
+ data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(
372
+ now,
373
+ loaded,
374
+ data.bitrateInterval
375
+ );
376
+ // Trigger a custom progress event with a total data property set
377
+ // to the file size(s) of the current upload and a loaded data
378
+ // property calculated accordingly:
379
+ this._trigger(
380
+ 'progress',
381
+ $.Event('progress', {
382
+ delegatedEvent: e
383
+ }),
384
+ data
385
+ );
386
+ // Trigger a global progress event for all current file uploads,
387
+ // including ajax calls queued for sequential file uploads:
388
+ this._trigger(
389
+ 'progressall',
390
+ $.Event('progressall', {
391
+ delegatedEvent: e
392
+ }),
393
+ this._progress
394
+ );
395
+ }
396
+ },
397
+
398
+ _initProgressListener: function(options) {
399
+ var that = this,
400
+ xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
401
+ // Accesss to the native XHR object is required to add event listeners
402
+ // for the upload progress event:
403
+ if (xhr.upload) {
404
+ $(xhr.upload).bind('progress', function(e) {
405
+ var oe = e.originalEvent;
406
+ // Make sure the progress event properties get copied over:
407
+ e.lengthComputable = oe.lengthComputable;
408
+ e.loaded = oe.loaded;
409
+ e.total = oe.total;
410
+ that._onProgress(e, options);
411
+ });
412
+ options.xhr = function() {
413
+ return xhr;
414
+ };
415
+ }
416
+ },
417
+
418
+ _isInstanceOf: function(type, obj) {
419
+ // Cross-frame instanceof check
420
+ return Object.prototype.toString.call(obj) === '[object ' + type + ']';
421
+ },
422
+
423
+ _initXHRData: function(options) {
424
+ var that = this,
425
+ formData,
426
+ file = options.files[0],
427
+ // Ignore non-multipart setting if not supported:
428
+ multipart = options.multipart || !$.support.xhrFileUpload,
429
+ paramName = $.type(options.paramName) === 'array' ?
430
+ options.paramName[0] : options.paramName;
431
+ options.headers = $.extend({}, options.headers);
432
+ if (options.contentRange) {
433
+ options.headers['Content-Range'] = options.contentRange;
434
+ }
435
+ if (!multipart || options.blob || !this._isInstanceOf('File', file)) {
436
+ options.headers['Content-Disposition'] = 'attachment; filename="' +
437
+ encodeURI(file.name) + '"';
438
+ }
439
+ if (!multipart) {
440
+ options.contentType = file.type || 'application/octet-stream';
441
+ options.data = options.blob || file;
442
+ } else if ($.support.xhrFormDataFileUpload) {
443
+ if (options.postMessage) {
444
+ // window.postMessage does not allow sending FormData
445
+ // objects, so we just add the File/Blob objects to
446
+ // the formData array and let the postMessage window
447
+ // create the FormData object out of this array:
448
+ formData = this._getFormData(options);
449
+ if (options.blob) {
450
+ formData.push({
451
+ name: paramName,
452
+ value: options.blob
453
+ });
454
+ } else {
455
+ $.each(options.files, function(index, file) {
456
+ formData.push({
457
+ name: ($.type(options.paramName) === 'array' &&
458
+ options.paramName[index]) || paramName,
459
+ value: file
460
+ });
461
+ });
462
+ }
463
+ } else {
464
+ if (that._isInstanceOf('FormData', options.formData)) {
465
+ formData = options.formData;
466
+ } else {
467
+ formData = new FormData();
468
+ $.each(this._getFormData(options), function(index, field) {
469
+ formData.append(field.name, field.value);
470
+ });
471
+ }
472
+ if (options.blob) {
473
+ formData.append(paramName, options.blob, file.name);
474
+ } else {
475
+ $.each(options.files, function(index, file) {
476
+ // This check allows the tests to run with
477
+ // dummy objects:
478
+ if (that._isInstanceOf('File', file) ||
479
+ that._isInstanceOf('Blob', file)) {
480
+ formData.append(
481
+ ($.type(options.paramName) === 'array' &&
482
+ options.paramName[index]) || paramName,
483
+ file,
484
+ file.uploadName || file.name
485
+ );
486
+ }
487
+ });
488
+ }
489
+ }
490
+ options.data = formData;
491
+ }
492
+ // Blob reference is not needed anymore, free memory:
493
+ options.blob = null;
494
+ },
495
+
496
+ _initIframeSettings: function(options) {
497
+ var targetHost = $('<a></a>').prop('href', options.url).prop('host');
498
+ // Setting the dataType to iframe enables the iframe transport:
499
+ options.dataType = 'iframe ' + (options.dataType || '');
500
+ // The iframe transport accepts a serialized array as form data:
501
+ options.formData = this._getFormData(options);
502
+ // Add redirect url to form data on cross-domain uploads:
503
+ if (options.redirect && targetHost && targetHost !== location.host) {
504
+ options.formData.push({
505
+ name: options.redirectParamName || 'redirect',
506
+ value: options.redirect
507
+ });
508
+ }
509
+ },
510
+
511
+ _initDataSettings: function(options) {
512
+ if (this._isXHRUpload(options)) {
513
+ if (!this._chunkedUpload(options, true)) {
514
+ if (!options.data) {
515
+ this._initXHRData(options);
516
+ }
517
+ this._initProgressListener(options);
518
+ }
519
+ if (options.postMessage) {
520
+ // Setting the dataType to postmessage enables the
521
+ // postMessage transport:
522
+ options.dataType = 'postmessage ' + (options.dataType || '');
523
+ }
524
+ } else {
525
+ this._initIframeSettings(options);
526
+ }
527
+ },
528
+
529
+ _getParamName: function(options) {
530
+ var fileInput = $(options.fileInput),
531
+ paramName = options.paramName;
532
+ if (!paramName) {
533
+ paramName = [];
534
+ fileInput.each(function() {
535
+ var input = $(this),
536
+ name = input.prop('name') || 'files[]',
537
+ i = (input.prop('files') || [1]).length;
538
+ while (i) {
539
+ paramName.push(name);
540
+ i -= 1;
541
+ }
542
+ });
543
+ if (!paramName.length) {
544
+ paramName = [fileInput.prop('name') || 'files[]'];
545
+ }
546
+ } else if (!$.isArray(paramName)) {
547
+ paramName = [paramName];
548
+ }
549
+ return paramName;
550
+ },
551
+
552
+ _initFormSettings: function(options) {
553
+ // Retrieve missing options from the input field and the
554
+ // associated form, if available:
555
+ if (!options.form || !options.form.length) {
556
+ options.form = $(options.fileInput.prop('form'));
557
+ // If the given file input doesn't have an associated form,
558
+ // use the default widget file input's form:
559
+ if (!options.form.length) {
560
+ options.form = $(this.options.fileInput.prop('form'));
561
+ }
562
+ }
563
+ options.paramName = this._getParamName(options);
564
+ if (!options.url) {
565
+ options.url = options.form.prop('action') || location.href;
566
+ }
567
+ // The HTTP request method must be "POST" or "PUT":
568
+ options.type = (options.type ||
569
+ ($.type(options.form.prop('method')) === 'string' &&
570
+ options.form.prop('method')) || ''
571
+ ).toUpperCase();
572
+ if (options.type !== 'POST' && options.type !== 'PUT' &&
573
+ options.type !== 'PATCH') {
574
+ options.type = 'POST';
575
+ }
576
+ if (!options.formAcceptCharset) {
577
+ options.formAcceptCharset = options.form.attr('accept-charset');
578
+ }
579
+ },
580
+
581
+ _getAJAXSettings: function(data) {
582
+ var options = $.extend({}, this.options, data);
583
+ this._initFormSettings(options);
584
+ this._initDataSettings(options);
585
+ return options;
586
+ },
587
+
588
+ // jQuery 1.6 doesn't provide .state(),
589
+ // while jQuery 1.8+ removed .isRejected() and .isResolved():
590
+ _getDeferredState: function(deferred) {
591
+ if (deferred.state) {
592
+ return deferred.state();
593
+ }
594
+ if (deferred.isResolved()) {
595
+ return 'resolved';
596
+ }
597
+ if (deferred.isRejected()) {
598
+ return 'rejected';
599
+ }
600
+ return 'pending';
601
+ },
602
+
603
+ // Maps jqXHR callbacks to the equivalent
604
+ // methods of the given Promise object:
605
+ _enhancePromise: function(promise) {
606
+ promise.success = promise.done;
607
+ promise.error = promise.fail;
608
+ promise.complete = promise.always;
609
+ return promise;
610
+ },
611
+
612
+ // Creates and returns a Promise object enhanced with
613
+ // the jqXHR methods abort, success, error and complete:
614
+ _getXHRPromise: function(resolveOrReject, context, args) {
615
+ var dfd = $.Deferred(),
616
+ promise = dfd.promise();
617
+ context = context || this.options.context || promise;
618
+ if (resolveOrReject === true) {
619
+ dfd.resolveWith(context, args);
620
+ } else if (resolveOrReject === false) {
621
+ dfd.rejectWith(context, args);
622
+ }
623
+ promise.abort = dfd.promise;
624
+ return this._enhancePromise(promise);
625
+ },
626
+
627
+ // Adds convenience methods to the data callback argument:
628
+ _addConvenienceMethods: function(e, data) {
629
+ var that = this,
630
+ getPromise = function(args) {
631
+ return $.Deferred().resolveWith(that, args).promise();
632
+ };
633
+ data.process = function(resolveFunc, rejectFunc) {
634
+ if (resolveFunc || rejectFunc) {
635
+ data._processQueue = this._processQueue =
636
+ (this._processQueue || getPromise([this])).pipe(
637
+ function() {
638
+ if (data.errorThrown) {
639
+ return $.Deferred()
640
+ .rejectWith(that, [data]).promise();
641
+ }
642
+ return getPromise(arguments);
643
+ }
644
+ ).pipe(resolveFunc, rejectFunc);
645
+ }
646
+ return this._processQueue || getPromise([this]);
647
+ };
648
+ data.submit = function() {
649
+ if (this.state() !== 'pending') {
650
+ data.jqXHR = this.jqXHR =
651
+ (that._trigger(
652
+ 'submit',
653
+ $.Event('submit', {
654
+ delegatedEvent: e
655
+ }),
656
+ this
657
+ ) !== false) && that._onSend(e, this);
658
+ }
659
+ return this.jqXHR || that._getXHRPromise();
660
+ };
661
+ data.abort = function() {
662
+ if (this.jqXHR) {
663
+ return this.jqXHR.abort();
664
+ }
665
+ this.errorThrown = 'abort';
666
+ that._trigger('fail', null, this);
667
+ return that._getXHRPromise(false);
668
+ };
669
+ data.state = function() {
670
+ if (this.jqXHR) {
671
+ return that._getDeferredState(this.jqXHR);
672
+ }
673
+ if (this._processQueue) {
674
+ return that._getDeferredState(this._processQueue);
675
+ }
676
+ };
677
+ data.processing = function() {
678
+ return !this.jqXHR && this._processQueue && that
679
+ ._getDeferredState(this._processQueue) === 'pending';
680
+ };
681
+ data.progress = function() {
682
+ return this._progress;
683
+ };
684
+ data.response = function() {
685
+ return this._response;
686
+ };
687
+ },
688
+
689
+ // Parses the Range header from the server response
690
+ // and returns the uploaded bytes:
691
+ _getUploadedBytes: function(jqXHR) {
692
+ var range = jqXHR.getResponseHeader('Range'),
693
+ parts = range && range.split('-'),
694
+ upperBytesPos = parts && parts.length > 1 &&
695
+ parseInt(parts[1], 10);
696
+ return upperBytesPos && upperBytesPos + 1;
697
+ },
698
+
699
+ // Uploads a file in multiple, sequential requests
700
+ // by splitting the file up in multiple blob chunks.
701
+ // If the second parameter is true, only tests if the file
702
+ // should be uploaded in chunks, but does not invoke any
703
+ // upload requests:
704
+ _chunkedUpload: function(options, testOnly) {
705
+ options.uploadedBytes = options.uploadedBytes || 0;
706
+ var that = this,
707
+ file = options.files[0],
708
+ fs = file.size,
709
+ ub = options.uploadedBytes,
710
+ mcs = options.maxChunkSize || fs,
711
+ slice = this._blobSlice,
712
+ dfd = $.Deferred(),
713
+ promise = dfd.promise(),
714
+ jqXHR,
715
+ upload;
716
+ if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
717
+ options.data) {
718
+ return false;
719
+ }
720
+ if (testOnly) {
721
+ return true;
722
+ }
723
+ if (ub >= fs) {
724
+ file.error = options.i18n('uploadedBytes');
725
+ return this._getXHRPromise(
726
+ false,
727
+ options.context,
728
+ [null, 'error', file.error]
729
+ );
730
+ }
731
+ // The chunk upload method:
732
+ upload = function() {
733
+ // Clone the options object for each chunk upload:
734
+ var o = $.extend({}, options),
735
+ currentLoaded = o._progress.loaded;
736
+ o.blob = slice.call(
737
+ file,
738
+ ub,
739
+ ub + mcs,
740
+ file.type
741
+ );
742
+ // Store the current chunk size, as the blob itself
743
+ // will be dereferenced after data processing:
744
+ o.chunkSize = o.blob.size;
745
+ // Expose the chunk bytes position range:
746
+ o.contentRange = 'bytes ' + ub + '-' +
747
+ (ub + o.chunkSize - 1) + '/' + fs;
748
+ // Process the upload data (the blob and potential form data):
749
+ that._initXHRData(o);
750
+ // Add progress listeners for this chunk upload:
751
+ that._initProgressListener(o);
752
+ jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) ||
753
+ that._getXHRPromise(false, o.context))
754
+ .done(function(result, textStatus, jqXHR) {
755
+ ub = that._getUploadedBytes(jqXHR) ||
756
+ (ub + o.chunkSize);
757
+ // Create a progress event if no final progress event
758
+ // with loaded equaling total has been triggered
759
+ // for this chunk:
760
+ if (currentLoaded + o.chunkSize - o._progress.loaded) {
761
+ that._onProgress($.Event('progress', {
762
+ lengthComputable: true,
763
+ loaded: ub - o.uploadedBytes,
764
+ total: ub - o.uploadedBytes
765
+ }), o);
766
+ }
767
+ options.uploadedBytes = o.uploadedBytes = ub;
768
+ o.result = result;
769
+ o.textStatus = textStatus;
770
+ o.jqXHR = jqXHR;
771
+ that._trigger('chunkdone', null, o);
772
+ that._trigger('chunkalways', null, o);
773
+ if (ub < fs) {
774
+ // File upload not yet complete,
775
+ // continue with the next chunk:
776
+ upload();
777
+ } else {
778
+ dfd.resolveWith(
779
+ o.context,
780
+ [result, textStatus, jqXHR]
781
+ );
782
+ }
783
+ })
784
+ .fail(function(jqXHR, textStatus, errorThrown) {
785
+ o.jqXHR = jqXHR;
786
+ o.textStatus = textStatus;
787
+ o.errorThrown = errorThrown;
788
+ that._trigger('chunkfail', null, o);
789
+ that._trigger('chunkalways', null, o);
790
+ dfd.rejectWith(
791
+ o.context,
792
+ [jqXHR, textStatus, errorThrown]
793
+ );
794
+ });
795
+ };
796
+ this._enhancePromise(promise);
797
+ promise.abort = function() {
798
+ return jqXHR.abort();
799
+ };
800
+ upload();
801
+ return promise;
802
+ },
803
+
804
+ _beforeSend: function(e, data) {
805
+ if (this._active === 0) {
806
+ // the start callback is triggered when an upload starts
807
+ // and no other uploads are currently running,
808
+ // equivalent to the global ajaxStart event:
809
+ this._trigger('start');
810
+ // Set timer for global bitrate progress calculation:
811
+ this._bitrateTimer = new this._BitrateTimer();
812
+ // Reset the global progress values:
813
+ this._progress.loaded = this._progress.total = 0;
814
+ this._progress.bitrate = 0;
815
+ }
816
+ // Make sure the container objects for the .response() and
817
+ // .progress() methods on the data object are available
818
+ // and reset to their initial state:
819
+ this._initResponseObject(data);
820
+ this._initProgressObject(data);
821
+ data._progress.loaded = data.loaded = data.uploadedBytes || 0;
822
+ data._progress.total = data.total = this._getTotal(data.files) || 1;
823
+ data._progress.bitrate = data.bitrate = 0;
824
+ this._active += 1;
825
+ // Initialize the global progress values:
826
+ this._progress.loaded += data.loaded;
827
+ this._progress.total += data.total;
828
+ },
829
+
830
+ _onDone: function(result, textStatus, jqXHR, options) {
831
+ var total = options._progress.total,
832
+ response = options._response;
833
+ if (options._progress.loaded < total) {
834
+ // Create a progress event if no final progress event
835
+ // with loaded equaling total has been triggered:
836
+ this._onProgress($.Event('progress', {
837
+ lengthComputable: true,
838
+ loaded: total,
839
+ total: total
840
+ }), options);
841
+ }
842
+ response.result = options.result = result;
843
+ response.textStatus = options.textStatus = textStatus;
844
+ response.jqXHR = options.jqXHR = jqXHR;
845
+ this._trigger('done', null, options);
846
+ },
847
+
848
+ _onFail: function(jqXHR, textStatus, errorThrown, options) {
849
+ var response = options._response;
850
+ if (options.recalculateProgress) {
851
+ // Remove the failed (error or abort) file upload from
852
+ // the global progress calculation:
853
+ this._progress.loaded -= options._progress.loaded;
854
+ this._progress.total -= options._progress.total;
855
+ }
856
+ response.jqXHR = options.jqXHR = jqXHR;
857
+ response.textStatus = options.textStatus = textStatus;
858
+ response.errorThrown = options.errorThrown = errorThrown;
859
+ this._trigger('fail', null, options);
860
+ },
861
+
862
+ _onAlways: function(jqXHRorResult, textStatus, jqXHRorError, options) {
863
+ // jqXHRorResult, textStatus and jqXHRorError are added to the
864
+ // options object via done and fail callbacks
865
+ this._trigger('always', null, options);
866
+ },
867
+
868
+ _onSend: function(e, data) {
869
+ if (!data.submit) {
870
+ this._addConvenienceMethods(e, data);
871
+ }
872
+ var that = this,
873
+ jqXHR,
874
+ aborted,
875
+ slot,
876
+ pipe,
877
+ options = that._getAJAXSettings(data),
878
+ send = function() {
879
+ that._sending += 1;
880
+ // Set timer for bitrate progress calculation:
881
+ options._bitrateTimer = new that._BitrateTimer();
882
+ jqXHR = jqXHR || (
883
+ ((aborted || that._trigger(
884
+ 'send',
885
+ $.Event('send', {
886
+ delegatedEvent: e
887
+ }),
888
+ options
889
+ ) === false) &&
890
+ that._getXHRPromise(false, options.context, aborted)) ||
891
+ that._chunkedUpload(options) || $.ajax(options)
892
+ ).done(function(result, textStatus, jqXHR) {
893
+ that._onDone(result, textStatus, jqXHR, options);
894
+ }).fail(function(jqXHR, textStatus, errorThrown) {
895
+ that._onFail(jqXHR, textStatus, errorThrown, options);
896
+ }).always(function(jqXHRorResult, textStatus, jqXHRorError) {
897
+ that._onAlways(
898
+ jqXHRorResult,
899
+ textStatus,
900
+ jqXHRorError,
901
+ options
902
+ );
903
+ that._sending -= 1;
904
+ that._active -= 1;
905
+ if (options.limitConcurrentUploads &&
906
+ options.limitConcurrentUploads > that._sending) {
907
+ // Start the next queued upload,
908
+ // that has not been aborted:
909
+ var nextSlot = that._slots.shift();
910
+ while (nextSlot) {
911
+ if (that._getDeferredState(nextSlot) === 'pending') {
912
+ nextSlot.resolve();
913
+ break;
914
+ }
915
+ nextSlot = that._slots.shift();
916
+ }
917
+ }
918
+ if (that._active === 0) {
919
+ // The stop callback is triggered when all uploads have
920
+ // been completed, equivalent to the global ajaxStop event:
921
+ that._trigger('stop');
922
+ }
923
+ });
924
+ return jqXHR;
925
+ };
926
+ this._beforeSend(e, options);
927
+ if (this.options.sequentialUploads ||
928
+ (this.options.limitConcurrentUploads &&
929
+ this.options.limitConcurrentUploads <= this._sending)) {
930
+ if (this.options.limitConcurrentUploads > 1) {
931
+ slot = $.Deferred();
932
+ this._slots.push(slot);
933
+ pipe = slot.pipe(send);
934
+ } else {
935
+ this._sequence = this._sequence.pipe(send, send);
936
+ pipe = this._sequence;
937
+ }
938
+ // Return the piped Promise object, enhanced with an abort method,
939
+ // which is delegated to the jqXHR object of the current upload,
940
+ // and jqXHR callbacks mapped to the equivalent Promise methods:
941
+ pipe.abort = function() {
942
+ aborted = [undefined, 'abort', 'abort'];
943
+ if (!jqXHR) {
944
+ if (slot) {
945
+ slot.rejectWith(options.context, aborted);
946
+ }
947
+ return send();
948
+ }
949
+ return jqXHR.abort();
950
+ };
951
+ return this._enhancePromise(pipe);
952
+ }
953
+ return send();
954
+ },
955
+
956
+ _onAdd: function(e, data) {
957
+ var that = this,
958
+ result = true,
959
+ options = $.extend({}, this.options, data),
960
+ files = data.files,
961
+ filesLength = files.length,
962
+ limit = options.limitMultiFileUploads,
963
+ limitSize = options.limitMultiFileUploadSize,
964
+ overhead = options.limitMultiFileUploadSizeOverhead,
965
+ batchSize = 0,
966
+ paramName = this._getParamName(options),
967
+ paramNameSet,
968
+ paramNameSlice,
969
+ fileSet,
970
+ i,
971
+ j = 0;
972
+ if (limitSize && (!filesLength || files[0].size === undefined)) {
973
+ limitSize = undefined;
974
+ }
975
+ if (!(options.singleFileUploads || limit || limitSize) ||
976
+ !this._isXHRUpload(options)) {
977
+ fileSet = [files];
978
+ paramNameSet = [paramName];
979
+ } else if (!(options.singleFileUploads || limitSize) && limit) {
980
+ fileSet = [];
981
+ paramNameSet = [];
982
+ for (i = 0; i < filesLength; i += limit) {
983
+ fileSet.push(files.slice(i, i + limit));
984
+ paramNameSlice = paramName.slice(i, i + limit);
985
+ if (!paramNameSlice.length) {
986
+ paramNameSlice = paramName;
987
+ }
988
+ paramNameSet.push(paramNameSlice);
989
+ }
990
+ } else if (!options.singleFileUploads && limitSize) {
991
+ fileSet = [];
992
+ paramNameSet = [];
993
+ for (i = 0; i < filesLength; i = i + 1) {
994
+ batchSize += files[i].size + overhead;
995
+ if (i + 1 === filesLength ||
996
+ ((batchSize + files[i + 1].size + overhead) > limitSize) ||
997
+ (limit && i + 1 - j >= limit)) {
998
+ fileSet.push(files.slice(j, i + 1));
999
+ paramNameSlice = paramName.slice(j, i + 1);
1000
+ if (!paramNameSlice.length) {
1001
+ paramNameSlice = paramName;
1002
+ }
1003
+ paramNameSet.push(paramNameSlice);
1004
+ j = i + 1;
1005
+ batchSize = 0;
1006
+ }
1007
+ }
1008
+ } else {
1009
+ paramNameSet = paramName;
1010
+ }
1011
+ data.originalFiles = files;
1012
+ $.each(fileSet || files, function(index, element) {
1013
+ var newData = $.extend({}, data);
1014
+ newData.files = fileSet ? element : [element];
1015
+ newData.paramName = paramNameSet[index];
1016
+ that._initResponseObject(newData);
1017
+ that._initProgressObject(newData);
1018
+ that._addConvenienceMethods(e, newData);
1019
+ result = that._trigger(
1020
+ 'add',
1021
+ $.Event('add', {
1022
+ delegatedEvent: e
1023
+ }),
1024
+ newData
1025
+ );
1026
+ return result;
1027
+ });
1028
+ return result;
1029
+ },
1030
+
1031
+ _replaceFileInput: function(input) {
1032
+ var inputClone = input.clone(true);
1033
+ $('<form></form>').append(inputClone)[0].reset();
1034
+ // Detaching allows to insert the fileInput on another form
1035
+ // without loosing the file input value:
1036
+ input.after(inputClone).detach();
1037
+ // Avoid memory leaks with the detached file input:
1038
+ $.cleanData(input.unbind('remove'));
1039
+ // Replace the original file input element in the fileInput
1040
+ // elements set with the clone, which has been copied including
1041
+ // event handlers:
1042
+ this.options.fileInput = this.options.fileInput.map(function(i, el) {
1043
+ if (el === input[0]) {
1044
+ return inputClone[0];
1045
+ }
1046
+ return el;
1047
+ });
1048
+ // If the widget has been initialized on the file input itself,
1049
+ // override this.element with the file input clone:
1050
+ if (input[0] === this.element[0]) {
1051
+ this.element = inputClone;
1052
+ }
1053
+ },
1054
+
1055
+ _handleFileTreeEntry: function(entry, path) {
1056
+ var that = this,
1057
+ dfd = $.Deferred(),
1058
+ errorHandler = function(e) {
1059
+ if (e && !e.entry) {
1060
+ e.entry = entry;
1061
+ }
1062
+ // Since $.when returns immediately if one
1063
+ // Deferred is rejected, we use resolve instead.
1064
+ // This allows valid files and invalid items
1065
+ // to be returned together in one set:
1066
+ dfd.resolve([e]);
1067
+ },
1068
+ dirReader;
1069
+ path = path || '';
1070
+ if (entry.isFile) {
1071
+ if (entry._file) {
1072
+ // Workaround for Chrome bug #149735
1073
+ entry._file.relativePath = path;
1074
+ dfd.resolve(entry._file);
1075
+ } else {
1076
+ entry.file(function(file) {
1077
+ file.relativePath = path;
1078
+ dfd.resolve(file);
1079
+ }, errorHandler);
1080
+ }
1081
+ } else if (entry.isDirectory) {
1082
+ dirReader = entry.createReader();
1083
+ dirReader.readEntries(function(entries) {
1084
+ that._handleFileTreeEntries(
1085
+ entries,
1086
+ path + entry.name + '/'
1087
+ ).done(function(files) {
1088
+ dfd.resolve(files);
1089
+ }).fail(errorHandler);
1090
+ }, errorHandler);
1091
+ } else {
1092
+ // Return an empy list for file system items
1093
+ // other than files or directories:
1094
+ dfd.resolve([]);
1095
+ }
1096
+ return dfd.promise();
1097
+ },
1098
+
1099
+ _handleFileTreeEntries: function(entries, path) {
1100
+ var that = this;
1101
+ return $.when.apply(
1102
+ $,
1103
+ $.map(entries, function(entry) {
1104
+ return that._handleFileTreeEntry(entry, path);
1105
+ })
1106
+ ).pipe(function() {
1107
+ return Array.prototype.concat.apply(
1108
+ [],
1109
+ arguments
1110
+ );
1111
+ });
1112
+ },
1113
+
1114
+ _getDroppedFiles: function(dataTransfer) {
1115
+ dataTransfer = dataTransfer || {};
1116
+ var items = dataTransfer.items;
1117
+ if (items && items.length && (items[0].webkitGetAsEntry ||
1118
+ items[0].getAsEntry)) {
1119
+ return this._handleFileTreeEntries(
1120
+ $.map(items, function(item) {
1121
+ var entry;
1122
+ if (item.webkitGetAsEntry) {
1123
+ entry = item.webkitGetAsEntry();
1124
+ if (entry) {
1125
+ // Workaround for Chrome bug #149735:
1126
+ entry._file = item.getAsFile();
1127
+ }
1128
+ return entry;
1129
+ }
1130
+ return item.getAsEntry();
1131
+ })
1132
+ );
1133
+ }
1134
+ return $.Deferred().resolve(
1135
+ $.makeArray(dataTransfer.files)
1136
+ ).promise();
1137
+ },
1138
+
1139
+ _getSingleFileInputFiles: function(fileInput) {
1140
+ fileInput = $(fileInput);
1141
+ var entries = fileInput.prop('webkitEntries') ||
1142
+ fileInput.prop('entries'),
1143
+ files,
1144
+ value;
1145
+ if (entries && entries.length) {
1146
+ return this._handleFileTreeEntries(entries);
1147
+ }
1148
+ files = $.makeArray(fileInput.prop('files'));
1149
+ if (!files.length) {
1150
+ value = fileInput.prop('value');
1151
+ if (!value) {
1152
+ return $.Deferred().resolve([]).promise();
1153
+ }
1154
+ // If the files property is not available, the browser does not
1155
+ // support the File API and we add a pseudo File object with
1156
+ // the input value as name with path information removed:
1157
+ files = [{
1158
+ name: value.replace(/^.*\\/, '')
1159
+ }];
1160
+ } else if (files[0].name === undefined && files[0].fileName) {
1161
+ // File normalization for Safari 4 and Firefox 3:
1162
+ $.each(files, function(index, file) {
1163
+ file.name = file.fileName;
1164
+ file.size = file.fileSize;
1165
+ });
1166
+ }
1167
+ return $.Deferred().resolve(files).promise();
1168
+ },
1169
+
1170
+ _getFileInputFiles: function(fileInput) {
1171
+ if (!(fileInput instanceof $) || fileInput.length === 1) {
1172
+ return this._getSingleFileInputFiles(fileInput);
1173
+ }
1174
+ return $.when.apply(
1175
+ $,
1176
+ $.map(fileInput, this._getSingleFileInputFiles)
1177
+ ).pipe(function() {
1178
+ return Array.prototype.concat.apply(
1179
+ [],
1180
+ arguments
1181
+ );
1182
+ });
1183
+ },
1184
+
1185
+ _onChange: function(e) {
1186
+ var that = this,
1187
+ data = {
1188
+ fileInput: $(e.target),
1189
+ form: $(e.target.form)
1190
+ };
1191
+ this._getFileInputFiles(data.fileInput).always(function(files) {
1192
+ data.files = files;
1193
+ if (that.options.replaceFileInput) {
1194
+ that._replaceFileInput(data.fileInput);
1195
+ }
1196
+ if (that._trigger(
1197
+ 'change',
1198
+ $.Event('change', {
1199
+ delegatedEvent: e
1200
+ }),
1201
+ data
1202
+ ) !== false) {
1203
+ that._onAdd(e, data);
1204
+ }
1205
+ });
1206
+ },
1207
+
1208
+ _onPaste: function(e) {
1209
+ var items = e.originalEvent && e.originalEvent.clipboardData &&
1210
+ e.originalEvent.clipboardData.items,
1211
+ data = {
1212
+ files: []
1213
+ };
1214
+ if (items && items.length) {
1215
+ $.each(items, function(index, item) {
1216
+ var file = item.getAsFile && item.getAsFile();
1217
+ if (file) {
1218
+ data.files.push(file);
1219
+ }
1220
+ });
1221
+ if (this._trigger(
1222
+ 'paste',
1223
+ $.Event('paste', {
1224
+ delegatedEvent: e
1225
+ }),
1226
+ data
1227
+ ) !== false) {
1228
+ this._onAdd(e, data);
1229
+ }
1230
+ }
1231
+ },
1232
+
1233
+ _onDrop: function(e) {
1234
+ e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
1235
+ var that = this,
1236
+ dataTransfer = e.dataTransfer,
1237
+ data = {};
1238
+ if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
1239
+ e.preventDefault();
1240
+ this._getDroppedFiles(dataTransfer).always(function(files) {
1241
+ data.files = files;
1242
+ if (that._trigger(
1243
+ 'drop',
1244
+ $.Event('drop', {
1245
+ delegatedEvent: e
1246
+ }),
1247
+ data
1248
+ ) !== false) {
1249
+ that._onAdd(e, data);
1250
+ }
1251
+ });
1252
+ }
1253
+ },
1254
+
1255
+ _onDragOver: function(e) {
1256
+ e.dataTransfer = e.originalEvent && e.originalEvent.dataTransfer;
1257
+ var dataTransfer = e.dataTransfer;
1258
+ if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1 &&
1259
+ this._trigger(
1260
+ 'dragover',
1261
+ $.Event('dragover', {
1262
+ delegatedEvent: e
1263
+ })
1264
+ ) !== false) {
1265
+ e.preventDefault();
1266
+ dataTransfer.dropEffect = 'copy';
1267
+ }
1268
+ },
1269
+
1270
+ _initEventHandlers: function() {
1271
+ if (this._isXHRUpload(this.options)) {
1272
+ this._on(this.options.dropZone, {
1273
+ dragover: this._onDragOver,
1274
+ drop: this._onDrop
1275
+ });
1276
+ this._on(this.options.pasteZone, {
1277
+ paste: this._onPaste
1278
+ });
1279
+ }
1280
+ if ($.support.fileInput) {
1281
+ this._on(this.options.fileInput, {
1282
+ change: this._onChange
1283
+ });
1284
+ }
1285
+ },
1286
+
1287
+ _destroyEventHandlers: function() {
1288
+ this._off(this.options.dropZone, 'dragover drop');
1289
+ this._off(this.options.pasteZone, 'paste');
1290
+ this._off(this.options.fileInput, 'change');
1291
+ },
1292
+
1293
+ _setOption: function(key, value) {
1294
+ var reinit = $.inArray(key, this._specialOptions) !== -1;
1295
+ if (reinit) {
1296
+ this._destroyEventHandlers();
1297
+ }
1298
+ this._super(key, value);
1299
+ if (reinit) {
1300
+ this._initSpecialOptions();
1301
+ this._initEventHandlers();
1302
+ }
1303
+ },
1304
+
1305
+ _initSpecialOptions: function() {
1306
+ var options = this.options;
1307
+ if (options.fileInput === undefined) {
1308
+ options.fileInput = this.element.is('input[type="file"]') ?
1309
+ this.element : this.element.find('input[type="file"]');
1310
+ } else if (!(options.fileInput instanceof $)) {
1311
+ options.fileInput = $(options.fileInput);
1312
+ }
1313
+ if (!(options.dropZone instanceof $)) {
1314
+ options.dropZone = $(options.dropZone);
1315
+ }
1316
+ if (!(options.pasteZone instanceof $)) {
1317
+ options.pasteZone = $(options.pasteZone);
1318
+ }
1319
+ },
1320
+
1321
+ _getRegExp: function(str) {
1322
+ var parts = str.split('/'),
1323
+ modifiers = parts.pop();
1324
+ parts.shift();
1325
+ return new RegExp(parts.join('/'), modifiers);
1326
+ },
1327
+
1328
+ _isRegExpOption: function(key, value) {
1329
+ return key !== 'url' && $.type(value) === 'string' &&
1330
+ /^\/.*\/[igm]{0,3}$/.test(value);
1331
+ },
1332
+
1333
+ _initDataAttributes: function() {
1334
+ var that = this,
1335
+ options = this.options,
1336
+ clone = $(this.element[0].cloneNode(false));
1337
+ // Initialize options set via HTML5 data-attributes:
1338
+ $.each(
1339
+ clone.data(),
1340
+ function(key, value) {
1341
+ var dataAttributeName = 'data-' +
1342
+ // Convert camelCase to hyphen-ated key:
1343
+ key.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
1344
+ if (clone.attr(dataAttributeName)) {
1345
+ if (that._isRegExpOption(key, value)) {
1346
+ value = that._getRegExp(value);
1347
+ }
1348
+ options[key] = value;
1349
+ }
1350
+ }
1351
+ );
1352
+ },
1353
+
1354
+ _create: function() {
1355
+ this._initDataAttributes();
1356
+ this._initSpecialOptions();
1357
+ this._slots = [];
1358
+ this._sequence = this._getXHRPromise(true);
1359
+ this._sending = this._active = 0;
1360
+ this._initProgressObject(this);
1361
+ this._initEventHandlers();
1362
+ },
1363
+
1364
+ // This method is exposed to the widget API and allows to query
1365
+ // the number of active uploads:
1366
+ active: function() {
1367
+ return this._active;
1368
+ },
1369
+
1370
+ // This method is exposed to the widget API and allows to query
1371
+ // the widget upload progress.
1372
+ // It returns an object with loaded, total and bitrate properties
1373
+ // for the running uploads:
1374
+ progress: function() {
1375
+ return this._progress;
1376
+ },
1377
+
1378
+ // This method is exposed to the widget API and allows adding files
1379
+ // using the fileupload API. The data parameter accepts an object which
1380
+ // must have a files property and can contain additional options:
1381
+ // .fileupload('add', {files: filesList});
1382
+ add: function(data) {
1383
+ var that = this;
1384
+ if (!data || this.options.disabled) {
1385
+ return;
1386
+ }
1387
+ if (data.fileInput && !data.files) {
1388
+ this._getFileInputFiles(data.fileInput).always(function(files) {
1389
+ data.files = files;
1390
+ that._onAdd(null, data);
1391
+ });
1392
+ } else {
1393
+ data.files = $.makeArray(data.files);
1394
+ this._onAdd(null, data);
1395
+ }
1396
+ },
1397
+
1398
+ // This method is exposed to the widget API and allows sending files
1399
+ // using the fileupload API. The data parameter accepts an object which
1400
+ // must have a files or fileInput property and can contain additional options:
1401
+ // .fileupload('send', {files: filesList});
1402
+ // The method returns a Promise object for the file upload call.
1403
+ send: function(data) {
1404
+ if (data && !this.options.disabled) {
1405
+ if (data.fileInput && !data.files) {
1406
+ var that = this,
1407
+ dfd = $.Deferred(),
1408
+ promise = dfd.promise(),
1409
+ jqXHR,
1410
+ aborted;
1411
+ promise.abort = function() {
1412
+ aborted = true;
1413
+ if (jqXHR) {
1414
+ return jqXHR.abort();
1415
+ }
1416
+ dfd.reject(null, 'abort', 'abort');
1417
+ return promise;
1418
+ };
1419
+ this._getFileInputFiles(data.fileInput).always(
1420
+ function(files) {
1421
+ if (aborted) {
1422
+ return;
1423
+ }
1424
+ if (!files.length) {
1425
+ dfd.reject();
1426
+ return;
1427
+ }
1428
+ data.files = files;
1429
+ jqXHR = that._onSend(null, data).then(
1430
+ function(result, textStatus, jqXHR) {
1431
+ dfd.resolve(result, textStatus, jqXHR);
1432
+ },
1433
+ function(jqXHR, textStatus, errorThrown) {
1434
+ dfd.reject(jqXHR, textStatus, errorThrown);
1435
+ }
1436
+ );
1437
+ }
1438
+ );
1439
+ return this._enhancePromise(promise);
1440
+ }
1441
+ data.files = $.makeArray(data.files);
1442
+ if (data.files.length) {
1443
+ return this._onSend(null, data);
1444
+ }
1445
+ }
1446
+ return this._getXHRPromise(false, data && data.context);
1447
+ }
1448
+
1449
+ });
1450
+
1451
+ }));