1/**! 2 * AngularJS file upload directives and services. Supoorts: file upload/drop/paste, resume, cancel/abort, 3 * progress, resize, thumbnail, preview, validation and CORS 4 * FileAPI Flash shim for old browsers not supporting FormData 5 * @author Danial <[email protected]> 6 * @version 12.0.4
vendor: 14,095 bytes, lines 6-421
6 7 */ 8 9(function () { 10 /** @namespace FileAPI.noContentTimeout */ 11 12 function patchXHR(fnName, newFn) { 13 window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]); 14 } 15 16 function redefineProp(xhr, prop, fn) { 17 try { 18 Object.defineProperty(xhr, prop, {get: fn}); 19 } catch (e) {/*ignore*/ 20 } 21 } 22 23 if (!window.FileAPI) { 24 window.FileAPI = {}; 25 } 26 27 if (!window.XMLHttpRequest) { 28 throw 'AJAX is not supported. XMLHttpRequest is not defined.'; 29 } 30 31 FileAPI.shouldLoad = !window.FormData || FileAPI.forceLoad; 32 if (FileAPI.shouldLoad) { 33 var initializeUploadListener = function (xhr) { 34 if (!xhr.__listeners) { 35 if (!xhr.upload) xhr.upload = {}; 36 xhr.__listeners = []; 37 var origAddEventListener = xhr.upload.addEventListener; 38 xhr.upload.addEventListener = function (t, fn) { 39 xhr.__listeners[t] = fn; 40 if (origAddEventListener) origAddEventListener.apply(this, arguments); 41 }; 42 } 43 }; 44 45 patchXHR('open', function (orig) { 46 return function (m, url, b) { 47 initializeUploadListener(this); 48 this.__url = url; 49 try { 50 orig.apply(this, [m, url, b]); 51 } catch (e) { 52 if (e.message.indexOf('Access is denied') > -1) { 53 this.__origError = e; 54 orig.apply(this, [m, '_fix_for_ie_crossdomain__', b]); 55 } 56 } 57 }; 58 }); 59 60 patchXHR('getResponseHeader', function (orig) { 61 return function (h) { 62 return this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h])); 63 }; 64 }); 65 66 patchXHR('getAllResponseHeaders', function (orig) { 67 return function () { 68 return this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this)); 69 }; 70 }); 71 72 patchXHR('abort', function (orig) { 73 return function () { 74 return this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this)); 75 }; 76 }); 77 78 patchXHR('setRequestHeader', function (orig) { 79 return function (header, value) { 80 if (header === '__setXHR_') { 81 initializeUploadListener(this); 82 var val = value(this); 83 // fix for angular < 1.2.0 84 if (val instanceof Function) { 85 val(this); 86 } 87 } else { 88 this.__requestHeaders = this.__requestHeaders || {}; 89 this.__requestHeaders[header] = value; 90 orig.apply(this, arguments); 91 } 92 }; 93 }); 94 95 patchXHR('send', function (orig) { 96 return function () { 97 var xhr = this; 98 if (arguments[0] && arguments[0].__isFileAPIShim) { 99 var formData = arguments[0]; 100 var config = { 101 url: xhr.__url, 102 jsonp: false, //removes the callback form param 103 cache: true, //removes the ?fileapiXXX in the url 104 complete: function (err, fileApiXHR) { 105 if (err && angular.isString(err) && err.indexOf('#2174') !== -1) { 106 // this error seems to be fine the file is being uploaded properly. 107 err = null; 108 } 109 xhr.__completed = true; 110 if (!err && xhr.__listeners.load) 111 xhr.__listeners.load({ 112 type: 'load', 113 loaded: xhr.__loaded, 114 total: xhr.__total, 115 target: xhr, 116 lengthComputable: true 117 }); 118 if (!err && xhr.__listeners.loadend) 119 xhr.__listeners.loadend({ 120 type: 'loadend', 121 loaded: xhr.__loaded, 122 total: xhr.__total, 123 target: xhr, 124 lengthComputable: true 125 }); 126 if (err === 'abort' && xhr.__listeners.abort) 127 xhr.__listeners.abort({ 128 type: 'abort', 129 loaded: xhr.__loaded, 130 total: xhr.__total, 131 target: xhr, 132 lengthComputable: true 133 }); 134 if (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function () { 135 return (fileApiXHR.status === 0 && err && err !== 'abort') ? 500 : fileApiXHR.status; 136 }); 137 if (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function () { 138 return fileApiXHR.statusText; 139 }); 140 redefineProp(xhr, 'readyState', function () { 141 return 4; 142 }); 143 if (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function () { 144 return fileApiXHR.response; 145 }); 146 var resp = fileApiXHR.responseText || (err && fileApiXHR.status === 0 && err !== 'abort' ? err : undefined); 147 redefineProp(xhr, 'responseText', function () { 148 return resp; 149 }); 150 redefineProp(xhr, 'response', function () { 151 return resp; 152 }); 153 if (err) redefineProp(xhr, 'err', function () { 154 return err; 155 }); 156 xhr.__fileApiXHR = fileApiXHR; 157 if (xhr.onreadystatechange) xhr.onreadystatechange(); 158 if (xhr.onload) xhr.onload(); 159 }, 160 progress: function (e) { 161 e.target = xhr; 162 if (xhr.__listeners.progress) xhr.__listeners.progress(e); 163 xhr.__total = e.total; 164 xhr.__loaded = e.loaded; 165 if (e.total === e.loaded) { 166 // fix flash issue that doesn't call complete if there is no response text from the server 167 var _this = this; 168 setTimeout(function () { 169 if (!xhr.__completed) { 170 xhr.getAllResponseHeaders = function () { 171 }; 172 _this.complete(null, {status: 204, statusText: 'No Content'}); 173 } 174 }, FileAPI.noContentTimeout || 10000); 175 } 176 }, 177 headers: xhr.__requestHeaders 178 }; 179 config.data = {}; 180 config.files = {}; 181 for (var i = 0; i < formData.data.length; i++) { 182 var item = formData.data[i]; 183 if (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) { 184 config.files[item.key] = item.val; 185 } else { 186 config.data[item.key] = item.val; 187 } 188 } 189 190 setTimeout(function () { 191 if (!FileAPI.hasFlash) { 192 throw 'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"'; 193 } 194 xhr.__fileApiXHR = FileAPI.upload(config); 195 }, 1); 196 } else { 197 if (this.__origError) { 198 throw this.__origError; 199 } 200 orig.apply(xhr, arguments); 201 } 202 }; 203 }); 204 window.XMLHttpRequest.__isFileAPIShim = true; 205 window.FormData = FormData = function () { 206 return { 207 append: function (key, val, name) { 208 if (val.__isFileAPIBlobShim) { 209 val = val.data[0]; 210 } 211 this.data.push({ 212 key: key, 213 val: val, 214 name: name 215 }); 216 }, 217 data: [], 218 __isFileAPIShim: true 219 }; 220 }; 221 222 window.Blob = Blob = function (b) { 223 return { 224 data: b, 225 __isFileAPIBlobShim: true 226 }; 227 }; 228 } 229 230})(); 231 232(function () { 233 /** @namespace FileAPI.forceLoad */ 234 /** @namespace window.FileAPI.jsUrl */ 235 /** @namespace window.FileAPI.jsPath */ 236 237 function isInputTypeFile(elem) { 238 return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file'; 239 } 240 241 function hasFlash() { 242 try { 243 var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash'); 244 if (fo) return true; 245 } catch (e) { 246 if (navigator.mimeTypes['application/x-shockwave-flash'] !== undefined) return true; 247 } 248 return false; 249 } 250 251 function getOffset(obj) { 252 var left = 0, top = 0; 253 254 if (window.jQuery) { 255 return jQuery(obj).offset(); 256 } 257 258 if (obj.offsetParent) { 259 do { 260 left += (obj.offsetLeft - obj.scrollLeft); 261 top += (obj.offsetTop - obj.scrollTop); 262 obj = obj.offsetParent; 263 } while (obj); 264 } 265 return { 266 left: left, 267 top: top 268 }; 269 } 270 271 if (FileAPI.shouldLoad) { 272 FileAPI.hasFlash = hasFlash(); 273 274 //load FileAPI 275 if (FileAPI.forceLoad) { 276 FileAPI.html5 = false; 277 } 278 279 if (!FileAPI.upload) { 280 var jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src; 281 if (window.FileAPI.jsUrl) { 282 jsUrl = window.FileAPI.jsUrl; 283 } else if (window.FileAPI.jsPath) { 284 basePath = window.FileAPI.jsPath; 285 } else { 286 for (i = 0; i < allScripts.length; i++) { 287 src = allScripts[i].src; 288 index = src.search(/\/ng\-file\-upload[\-a-zA-z0-9\.]*\.js/); 289 if (index > -1) { 290 basePath = src.substring(0, index + 1); 291 break; 292 } 293 } 294 } 295 296 if (FileAPI.staticPath == null) FileAPI.staticPath = basePath; 297 script.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js'); 298 document.getElementsByTagName('head')[0].appendChild(script); 299 } 300 301 FileAPI.ngfFixIE = function (elem, fileElem, changeFn) { 302 if (!hasFlash()) { 303 throw 'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"'; 304 } 305 var fixInputStyle = function () { 306 var label = fileElem.parent(); 307 if (elem.attr('disabled')) { 308 if (label) label.removeClass('js-fileapi-wrapper'); 309 } else { 310 if (!fileElem.attr('__ngf_flash_')) { 311 fileElem.unbind('change'); 312 fileElem.unbind('click'); 313 fileElem.bind('change', function (evt) { 314 fileApiChangeFn.apply(this, [evt]); 315 changeFn.apply(this, [evt]); 316 }); 317 fileElem.attr('__ngf_flash_', 'true'); 318 } 319 label.addClass('js-fileapi-wrapper'); 320 if (!isInputTypeFile(elem)) { 321 label.css('position', 'absolute') 322 .css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px') 323 .css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px') 324 .css('filter', 'alpha(opacity=0)').css('display', elem.css('display')) 325 .css('overflow', 'hidden').css('z-index', '900000') 326 .css('visibility', 'visible'); 327 fileElem.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px') 328 .css('position', 'absolute').css('top', '0px').css('left', '0px'); 329 } 330 } 331 }; 332 333 elem.bind('mouseenter', fixInputStyle); 334 335 var fileApiChangeFn = function (evt) { 336 var files = FileAPI.getFiles(evt); 337 //just a double check for #233 338 for (var i = 0; i < files.length; i++) { 339 if (files[i].size === undefined) files[i].size = 0; 340 if (files[i].name === undefined) files[i].name = 'file'; 341 if (files[i].type === undefined) files[i].type = 'undefined'; 342 } 343 if (!evt.target) { 344 evt.target = {}; 345 } 346 evt.target.files = files; 347 // if evt.target.files is not writable use helper field 348 if (evt.target.files !== files) { 349 evt.__files_ = files; 350 } 351 (evt.__files_ || evt.target.files).item = function (i) { 352 return (evt.__files_ || evt.target.files)[i] || null; 353 }; 354 }; 355 }; 356 357 FileAPI.disableFileInput = function (elem, disable) { 358 if (disable) { 359 elem.removeClass('js-fileapi-wrapper'); 360 } else { 361 elem.addClass('js-fileapi-wrapper'); 362 } 363 }; 364 } 365})(); 366 367if (!window.FileReader) { 368 window.FileReader = function () { 369 var _this = this, loadStarted = false; 370 this.listeners = {}; 371 this.addEventListener = function (type, fn) { 372 _this.listeners[type] = _this.listeners[type] || []; 373 _this.listeners[type].push(fn); 374 }; 375 this.removeEventListener = function (type, fn) { 376 if (_this.listeners[type]) _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1); 377 }; 378 this.dispatchEvent = function (evt) { 379 var list = _this.listeners[evt.type]; 380 if (list) { 381 for (var i = 0; i < list.length; i++) { 382 list[i].call(_this, evt); 383 } 384 } 385 }; 386 this.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null; 387 388 var constructEvent = function (type, evt) { 389 var e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error}; 390 if (evt.result != null) e.target.result = evt.result; 391 return e; 392 }; 393 var listener = function (evt) { 394 if (!loadStarted) { 395 loadStarted = true; 396 if (_this.onloadstart) _this.onloadstart(constructEvent('loadstart', evt)); 397 } 398 var e; 399 if (evt.type === 'load') { 400 if (_this.onloadend) _this.onloadend(constructEvent('loadend', evt)); 401 e = constructEvent('load', evt); 402 if (_this.onload) _this.onload(e); 403 _this.dispatchEvent(e); 404 } else if (evt.type === 'progress') { 405 e = constructEvent('progress', evt); 406 if (_this.onprogress) _this.onprogress(e); 407 _this.dispatchEvent(e); 408 } else { 409 e = constructEvent('error', evt); 410 if (_this.onerror) _this.onerror(e); 411 _this.dispatchEvent(e); 412 } 413 }; 414 this.readAsDataURL = function (file) { 415 FileAPI.readAsDataURL(file, listener); 416 }; 417 this.readAsText = function (file) { 418 FileAPI.readAsText(file, listener); 419 }; 420 }; 421}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.