angular-file-upload-shim.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /**!
  2. * AngularJS file upload shim for HTML5 FormData
  3. * @author Danial <danial.farid@gmail.com>
  4. * @version 1.1.10
  5. */
  6. (function() {
  7. if (window.XMLHttpRequest) {
  8. if (window.FormData) {
  9. // allow access to Angular XHR private field: https://github.com/angular/angular.js/issues/1934
  10. XMLHttpRequest = (function(origXHR) {
  11. return function() {
  12. var xhr = new origXHR();
  13. xhr.send = (function(orig) {
  14. return function() {
  15. if (arguments[0] instanceof FormData && arguments[0].__setXHR_) {
  16. var formData = arguments[0];
  17. formData.__setXHR_(xhr);
  18. }
  19. orig.apply(xhr, arguments);
  20. }
  21. })(xhr.send);
  22. return xhr;
  23. }
  24. })(XMLHttpRequest);
  25. } else {
  26. XMLHttpRequest = (function(origXHR) {
  27. return function() {
  28. var xhr = new origXHR();
  29. var origSend = xhr.send;
  30. xhr.__requestHeaders = [];
  31. xhr.open = (function(orig) {
  32. xhr.upload = {
  33. addEventListener: function(t, fn, b) {
  34. if (t == 'progress') {
  35. xhr.__progress = fn;
  36. }
  37. }
  38. };
  39. return function(m, url, b) {
  40. orig.apply(xhr, [m, url, b]);
  41. xhr.__url = url;
  42. }
  43. })(xhr.open);
  44. xhr.getResponseHeader = (function(orig) {
  45. return function(h) {
  46. return xhr.__fileApiXHR ? xhr.__fileApiXHR.getResponseHeader(h) : orig.apply(xhr, [h]);
  47. }
  48. })(xhr.getResponseHeader);
  49. xhr.getAllResponseHeaders = (function(orig) {
  50. return function() {
  51. return xhr.__fileApiXHR ? xhr.__fileApiXHR.getAllResponseHeaders() : orig.apply(xhr);
  52. }
  53. })(xhr.getAllResponseHeaders);
  54. xhr.abort = (function(orig) {
  55. return function() {
  56. return xhr.__fileApiXHR ? xhr.__fileApiXHR.abort() : (orig == null ? null : orig.apply(xhr));
  57. }
  58. })(xhr.abort);
  59. xhr.send = function() {
  60. if (arguments[0] != null && arguments[0].__isShim && arguments[0].__setXHR_) {
  61. var formData = arguments[0];
  62. if (arguments[0].__setXHR_) {
  63. var formData = arguments[0];
  64. formData.__setXHR_(xhr);
  65. }
  66. var config = {
  67. url: xhr.__url,
  68. complete: function(err, fileApiXHR) {
  69. Object.defineProperty(xhr, 'status', {get: function() {return fileApiXHR.status}});
  70. Object.defineProperty(xhr, 'statusText', {get: function() {return fileApiXHR.statusText}});
  71. Object.defineProperty(xhr, 'readyState', {get: function() {return 4}});
  72. Object.defineProperty(xhr, 'response', {get: function() {return fileApiXHR.response}});
  73. Object.defineProperty(xhr, 'responseText', {get: function() {return fileApiXHR.responseText}});
  74. xhr.__fileApiXHR = fileApiXHR;
  75. xhr.onreadystatechange();
  76. },
  77. progress: function(e) {
  78. xhr.__progress(e);
  79. },
  80. headers: xhr.__requestHeaders
  81. }
  82. config.data = {};
  83. config.files = {}
  84. for (var i = 0; i < formData.data.length; i++) {
  85. var item = formData.data[i];
  86. if (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) {
  87. config.files[item.key] = item.val;
  88. } else {
  89. config.data[item.key] = item.val;
  90. }
  91. }
  92. setTimeout(function() {
  93. xhr.__fileApiXHR = FileAPI.upload(config);
  94. }, 1);
  95. } else {
  96. origSend.apply(xhr, arguments);
  97. }
  98. }
  99. return xhr;
  100. }
  101. })(XMLHttpRequest);
  102. }
  103. }
  104. if (!window.FormData) {
  105. var hasFlash = false;
  106. try {
  107. var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash');
  108. if (fo) hasFlash = true;
  109. } catch(e) {
  110. if (navigator.mimeTypes["application/x-shockwave-flash"] != undefined) hasFlash = true;
  111. }
  112. var wrapFileApi = function(elem) {
  113. if (!elem.__isWrapped && (elem.getAttribute('ng-file-select') != null || elem.getAttribute('data-ng-file-select') != null)) {
  114. var wrap = document.createElement('div');
  115. wrap.innerHTML = '<div class="js-fileapi-wrapper" style="position:relative; overflow:hidden"></div>';
  116. wrap = wrap.firstChild;
  117. var parent = elem.parentNode;
  118. parent.insertBefore(wrap, elem);
  119. parent.removeChild(elem);
  120. wrap.appendChild(elem);
  121. if (!hasFlash) {
  122. wrap.appendChild(document.createTextNode('Flash is required'));
  123. }
  124. elem.__isWrapped = true;
  125. }
  126. };
  127. var changeFnWrapper = function(fn) {
  128. return function(evt) {
  129. var files = FileAPI.getFiles(evt);
  130. if (!evt.target) {
  131. evt.target = {};
  132. }
  133. evt.target.files = files;
  134. evt.target.files.item = function(i) {
  135. return evt.target.files[i] || null;
  136. }
  137. fn(evt);
  138. };
  139. };
  140. var isFileChange = function(elem, e) {
  141. return (e.toLowerCase() === 'change' || e.toLowerCase() === 'onchange') && elem.getAttribute('type') == 'file';
  142. }
  143. if (HTMLInputElement.prototype.addEventListener) {
  144. HTMLInputElement.prototype.addEventListener = (function(origAddEventListener) {
  145. return function(e, fn, b, d) {
  146. if (isFileChange(this, e)) {
  147. wrapFileApi(this);
  148. origAddEventListener.apply(this, [e, changeFnWrapper(fn), b, d]);
  149. } else {
  150. origAddEventListener.apply(this, [e, fn, b, d]);
  151. }
  152. }
  153. })(HTMLInputElement.prototype.addEventListener);
  154. }
  155. if (HTMLInputElement.prototype.attachEvent) {
  156. HTMLInputElement.prototype.attachEvent = (function(origAttachEvent) {
  157. return function(e, fn) {
  158. if (isFileChange(this, e)) {
  159. wrapFileApi(this);
  160. origAttachEvent.apply(this, [e, changeFnWrapper(fn)]);
  161. } else {
  162. origAttachEvent.apply(this, [e, fn]);
  163. }
  164. }
  165. })(HTMLInputElement.prototype.attachEvent);
  166. }
  167. window.FormData = FormData = function() {
  168. return {
  169. append: function(key, val, name) {
  170. this.data.push({
  171. key: key,
  172. val: val,
  173. name: name
  174. });
  175. },
  176. data: [],
  177. __isShim: true
  178. };
  179. };
  180. (function () {
  181. //load FileAPI
  182. if (!window.FileAPI || !FileAPI.upload) {
  183. var base = '', script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src;
  184. if (window.FileAPI && window.FileAPI.jsPath) {
  185. base = window.FileAPI.jsPath;
  186. } else {
  187. for (i = 0; i < allScripts.length; i++) {
  188. src = allScripts[i].src;
  189. index = src.indexOf('angular-file-upload-shim.js')
  190. if (index == -1) {
  191. index = src.indexOf('angular-file-upload-shim.min.js');
  192. }
  193. if (index > -1) {
  194. base = src.substring(0, index);
  195. break;
  196. }
  197. }
  198. }
  199. if (!window.FileAPI || FileAPI.staticPath == null) {
  200. FileAPI = {
  201. staticPath: base
  202. }
  203. }
  204. script.setAttribute('src', base + "FileAPI.min.js");
  205. document.getElementsByTagName('head')[0].appendChild(script);
  206. }
  207. })();
  208. }})();