jquery.fileupload-fp.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * jQuery File Upload File Processing Plugin 1.2.1
  3. * https://github.com/blueimp/jQuery-File-Upload
  4. *
  5. * Copyright 2012, Sebastian Tschan
  6. * https://blueimp.net
  7. *
  8. * Licensed under the MIT license:
  9. * http://www.opensource.org/licenses/MIT
  10. */
  11. /*jslint nomen: true, unparam: true, regexp: true */
  12. /*global define, window, document */
  13. (function (factory) {
  14. 'use strict';
  15. if (typeof define === 'function' && define.amd) {
  16. // Register as an anonymous AMD module:
  17. define([
  18. 'jquery',
  19. 'load-image',
  20. 'canvas-to-blob',
  21. './jquery.fileupload'
  22. ], factory);
  23. } else {
  24. // Browser globals:
  25. factory(
  26. window.jQuery,
  27. window.loadImage
  28. );
  29. }
  30. }(function ($, loadImage) {
  31. 'use strict';
  32. // The File Upload FP version extends the fileupload widget
  33. // with file processing functionality:
  34. $.widget('blueimp.fileupload', $.blueimp.fileupload, {
  35. options: {
  36. // The list of file processing actions:
  37. process: [
  38. /*
  39. {
  40. action: 'load',
  41. fileTypes: /^image\/(gif|jpeg|png)$/,
  42. maxFileSize: 20000000 // 20MB
  43. },
  44. {
  45. action: 'resize',
  46. maxWidth: 1920,
  47. maxHeight: 1200,
  48. minWidth: 800,
  49. minHeight: 600
  50. },
  51. {
  52. action: 'save'
  53. }
  54. */
  55. ],
  56. // The add callback is invoked as soon as files are added to the
  57. // fileupload widget (via file input selection, drag & drop or add
  58. // API call). See the basic file upload widget for more information:
  59. add: function (e, data) {
  60. $(this).fileupload('process', data).done(function () {
  61. data.submit();
  62. });
  63. }
  64. },
  65. processActions: {
  66. // Loads the image given via data.files and data.index
  67. // as img element if the browser supports canvas.
  68. // Accepts the options fileTypes (regular expression)
  69. // and maxFileSize (integer) to limit the files to load:
  70. load: function (data, options) {
  71. var that = this,
  72. file = data.files[data.index],
  73. dfd = $.Deferred();
  74. if (window.HTMLCanvasElement &&
  75. window.HTMLCanvasElement.prototype.toBlob &&
  76. ($.type(options.maxFileSize) !== 'number' ||
  77. file.size < options.maxFileSize) &&
  78. (!options.fileTypes ||
  79. options.fileTypes.test(file.type))) {
  80. loadImage(
  81. file,
  82. function (img) {
  83. if (!img.src) {
  84. return dfd.rejectWith(that, [data]);
  85. }
  86. data.img = img;
  87. dfd.resolveWith(that, [data]);
  88. }
  89. );
  90. } else {
  91. dfd.rejectWith(that, [data]);
  92. }
  93. return dfd.promise();
  94. },
  95. // Resizes the image given as data.img and updates
  96. // data.canvas with the resized image as canvas element.
  97. // Accepts the options maxWidth, maxHeight, minWidth and
  98. // minHeight to scale the given image:
  99. resize: function (data, options) {
  100. var img = data.img,
  101. canvas;
  102. options = $.extend({canvas: true}, options);
  103. if (img) {
  104. canvas = loadImage.scale(img, options);
  105. if (canvas.width !== img.width ||
  106. canvas.height !== img.height) {
  107. data.canvas = canvas;
  108. }
  109. }
  110. return data;
  111. },
  112. // Saves the processed image given as data.canvas
  113. // inplace at data.index of data.files:
  114. save: function (data, options) {
  115. // Do nothing if no processing has happened:
  116. if (!data.canvas) {
  117. return data;
  118. }
  119. var that = this,
  120. file = data.files[data.index],
  121. name = file.name,
  122. dfd = $.Deferred(),
  123. callback = function (blob) {
  124. if (!blob.name) {
  125. if (file.type === blob.type) {
  126. blob.name = file.name;
  127. } else if (file.name) {
  128. blob.name = file.name.replace(
  129. /\..+$/,
  130. '.' + blob.type.substr(6)
  131. );
  132. }
  133. }
  134. // Store the created blob at the position
  135. // of the original file in the files list:
  136. data.files[data.index] = blob;
  137. dfd.resolveWith(that, [data]);
  138. };
  139. // Use canvas.mozGetAsFile directly, to retain the filename, as
  140. // Gecko doesn't support the filename option for FormData.append:
  141. if (data.canvas.mozGetAsFile) {
  142. callback(data.canvas.mozGetAsFile(
  143. (/^image\/(jpeg|png)$/.test(file.type) && name) ||
  144. ((name && name.replace(/\..+$/, '')) ||
  145. 'blob') + '.png',
  146. file.type
  147. ));
  148. } else {
  149. data.canvas.toBlob(callback, file.type);
  150. }
  151. return dfd.promise();
  152. }
  153. },
  154. // Resizes the file at the given index and stores the created blob at
  155. // the original position of the files list, returns a Promise object:
  156. _processFile: function (files, index, options) {
  157. var that = this,
  158. dfd = $.Deferred().resolveWith(that, [{
  159. files: files,
  160. index: index
  161. }]),
  162. chain = dfd.promise();
  163. that._processing += 1;
  164. $.each(options.process, function (i, settings) {
  165. chain = chain.pipe(function (data) {
  166. return that.processActions[settings.action]
  167. .call(this, data, settings);
  168. });
  169. });
  170. chain.always(function () {
  171. that._processing -= 1;
  172. if (that._processing === 0) {
  173. that.element
  174. .removeClass('fileupload-processing');
  175. }
  176. });
  177. if (that._processing === 1) {
  178. that.element.addClass('fileupload-processing');
  179. }
  180. return chain;
  181. },
  182. // Processes the files given as files property of the data parameter,
  183. // returns a Promise object that allows to bind a done handler, which
  184. // will be invoked after processing all files (inplace) is done:
  185. process: function (data) {
  186. var that = this,
  187. options = $.extend({}, this.options, data);
  188. if (options.process && options.process.length &&
  189. this._isXHRUpload(options)) {
  190. $.each(data.files, function (index, file) {
  191. that._processingQueue = that._processingQueue.pipe(
  192. function () {
  193. var dfd = $.Deferred();
  194. that._processFile(data.files, index, options)
  195. .always(function () {
  196. dfd.resolveWith(that);
  197. });
  198. return dfd.promise();
  199. }
  200. );
  201. });
  202. }
  203. return this._processingQueue;
  204. },
  205. _create: function () {
  206. this._super();
  207. this._processing = 0;
  208. this._processingQueue = $.Deferred().resolveWith(this)
  209. .promise();
  210. }
  211. });
  212. }));