/**! * AngularJS file upload directives and services. Supports: file upload/drop/paste, resume, cancel/abort, * progress, resize, thumbnail, preview, validation and CORS * FileAPI Flash shim for old browsers not supporting FormData * @author Danial * @version 12.2.13 */ (function () { /** @namespace FileAPI.noContentTimeout */ function patchXHR(fnName, newFn) { window.XMLHttpRequest.prototype[fnName] = newFn(window.XMLHttpRequest.prototype[fnName]); } function redefineProp(xhr, prop, fn) { try { Object.defineProperty(xhr, prop, {get: fn}); } catch (e) {/*ignore*/ } } if (!window.FileAPI) { window.FileAPI = {}; } if (!window.XMLHttpRequest) { throw 'AJAX is not supported. XMLHttpRequest is not defined.'; } FileAPI.shouldLoad = !window.FormData || FileAPI.forceLoad; if (FileAPI.shouldLoad) { var initializeUploadListener = function (xhr) { if (!xhr.__listeners) { if (!xhr.upload) xhr.upload = {}; xhr.__listeners = []; var origAddEventListener = xhr.upload.addEventListener; xhr.upload.addEventListener = function (t, fn) { xhr.__listeners[t] = fn; if (origAddEventListener) origAddEventListener.apply(this, arguments); }; } }; patchXHR('open', function (orig) { return function (m, url, b) { initializeUploadListener(this); this.__url = url; try { orig.apply(this, [m, url, b]); } catch (e) { if (e.message.indexOf('Access is denied') > -1) { this.__origError = e; orig.apply(this, [m, '_fix_for_ie_crossdomain__', b]); } } }; }); patchXHR('getResponseHeader', function (orig) { return function (h) { return this.__fileApiXHR && this.__fileApiXHR.getResponseHeader ? this.__fileApiXHR.getResponseHeader(h) : (orig == null ? null : orig.apply(this, [h])); }; }); patchXHR('getAllResponseHeaders', function (orig) { return function () { return this.__fileApiXHR && this.__fileApiXHR.getAllResponseHeaders ? this.__fileApiXHR.getAllResponseHeaders() : (orig == null ? null : orig.apply(this)); }; }); patchXHR('abort', function (orig) { return function () { return this.__fileApiXHR && this.__fileApiXHR.abort ? this.__fileApiXHR.abort() : (orig == null ? null : orig.apply(this)); }; }); patchXHR('setRequestHeader', function (orig) { return function (header, value) { if (header === '__setXHR_') { initializeUploadListener(this); var val = value(this); // fix for angular < 1.2.0 if (val instanceof Function) { val(this); } } else { this.__requestHeaders = this.__requestHeaders || {}; this.__requestHeaders[header] = value; orig.apply(this, arguments); } }; }); patchXHR('send', function (orig) { return function () { var xhr = this; if (arguments[0] && arguments[0].__isFileAPIShim) { var formData = arguments[0]; var config = { url: xhr.__url, jsonp: false, //removes the callback form param cache: true, //removes the ?fileapiXXX in the url complete: function (err, fileApiXHR) { if (err && angular.isString(err) && err.indexOf('#2174') !== -1) { // this error seems to be fine the file is being uploaded properly. err = null; } xhr.__completed = true; if (!err && xhr.__listeners.load) xhr.__listeners.load({ type: 'load', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true }); if (!err && xhr.__listeners.loadend) xhr.__listeners.loadend({ type: 'loadend', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true }); if (err === 'abort' && xhr.__listeners.abort) xhr.__listeners.abort({ type: 'abort', loaded: xhr.__loaded, total: xhr.__total, target: xhr, lengthComputable: true }); if (fileApiXHR.status !== undefined) redefineProp(xhr, 'status', function () { return (fileApiXHR.status === 0 && err && err !== 'abort') ? 500 : fileApiXHR.status; }); if (fileApiXHR.statusText !== undefined) redefineProp(xhr, 'statusText', function () { return fileApiXHR.statusText; }); redefineProp(xhr, 'readyState', function () { return 4; }); if (fileApiXHR.response !== undefined) redefineProp(xhr, 'response', function () { return fileApiXHR.response; }); var resp = fileApiXHR.responseText || (err && fileApiXHR.status === 0 && err !== 'abort' ? err : undefined); redefineProp(xhr, 'responseText', function () { return resp; }); redefineProp(xhr, 'response', function () { return resp; }); if (err) redefineProp(xhr, 'err', function () { return err; }); xhr.__fileApiXHR = fileApiXHR; if (xhr.onreadystatechange) xhr.onreadystatechange(); if (xhr.onload) xhr.onload(); }, progress: function (e) { e.target = xhr; if (xhr.__listeners.progress) xhr.__listeners.progress(e); xhr.__total = e.total; xhr.__loaded = e.loaded; if (e.total === e.loaded) { // fix flash issue that doesn't call complete if there is no response text from the server var _this = this; setTimeout(function () { if (!xhr.__completed) { xhr.getAllResponseHeaders = function () { }; _this.complete(null, {status: 204, statusText: 'No Content'}); } }, FileAPI.noContentTimeout || 10000); } }, headers: xhr.__requestHeaders }; config.data = {}; config.files = {}; for (var i = 0; i < formData.data.length; i++) { var item = formData.data[i]; if (item.val != null && item.val.name != null && item.val.size != null && item.val.type != null) { config.files[item.key] = item.val; } else { config.data[item.key] = item.val; } } setTimeout(function () { if (!FileAPI.hasFlash) { throw 'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"'; } xhr.__fileApiXHR = FileAPI.upload(config); }, 1); } else { if (this.__origError) { throw this.__origError; } orig.apply(xhr, arguments); } }; }); window.XMLHttpRequest.__isFileAPIShim = true; window.FormData = FormData = function () { return { append: function (key, val, name) { if (val.__isFileAPIBlobShim) { val = val.data[0]; } this.data.push({ key: key, val: val, name: name }); }, data: [], __isFileAPIShim: true }; }; window.Blob = Blob = function (b) { return { data: b, __isFileAPIBlobShim: true }; }; } })(); (function () { /** @namespace FileAPI.forceLoad */ /** @namespace window.FileAPI.jsUrl */ /** @namespace window.FileAPI.jsPath */ function isInputTypeFile(elem) { return elem[0].tagName.toLowerCase() === 'input' && elem.attr('type') && elem.attr('type').toLowerCase() === 'file'; } function hasFlash() { try { var fo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash'); if (fo) return true; } catch (e) { if (navigator.mimeTypes['application/x-shockwave-flash'] !== undefined) return true; } return false; } function getOffset(obj) { var left = 0, top = 0; if (window.jQuery) { return jQuery(obj).offset(); } if (obj.offsetParent) { do { left += (obj.offsetLeft - obj.scrollLeft); top += (obj.offsetTop - obj.scrollTop); obj = obj.offsetParent; } while (obj); } return { left: left, top: top }; } if (FileAPI.shouldLoad) { FileAPI.hasFlash = hasFlash(); //load FileAPI if (FileAPI.forceLoad) { FileAPI.html5 = false; } if (!FileAPI.upload) { var jsUrl, basePath, script = document.createElement('script'), allScripts = document.getElementsByTagName('script'), i, index, src; if (window.FileAPI.jsUrl) { jsUrl = window.FileAPI.jsUrl; } else if (window.FileAPI.jsPath) { basePath = window.FileAPI.jsPath; } else { for (i = 0; i < allScripts.length; i++) { src = allScripts[i].src; index = src.search(/\/ng\-file\-upload[\-a-zA-z0-9\.]*\.js/); if (index > -1) { basePath = src.substring(0, index + 1); break; } } } if (FileAPI.staticPath == null) FileAPI.staticPath = basePath; script.setAttribute('src', jsUrl || basePath + 'FileAPI.min.js'); document.getElementsByTagName('head')[0].appendChild(script); } FileAPI.ngfFixIE = function (elem, fileElem, changeFn) { if (!hasFlash()) { throw 'Adode Flash Player need to be installed. To check ahead use "FileAPI.hasFlash"'; } var fixInputStyle = function () { var label = fileElem.parent(); if (elem.attr('disabled')) { if (label) label.removeClass('js-fileapi-wrapper'); } else { if (!fileElem.attr('__ngf_flash_')) { fileElem.unbind('change'); fileElem.unbind('click'); fileElem.bind('change', function (evt) { fileApiChangeFn.apply(this, [evt]); changeFn.apply(this, [evt]); }); fileElem.attr('__ngf_flash_', 'true'); } label.addClass('js-fileapi-wrapper'); if (!isInputTypeFile(elem)) { label.css('position', 'absolute') .css('top', getOffset(elem[0]).top + 'px').css('left', getOffset(elem[0]).left + 'px') .css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px') .css('filter', 'alpha(opacity=0)').css('display', elem.css('display')) .css('overflow', 'hidden').css('z-index', '900000') .css('visibility', 'visible'); fileElem.css('width', elem[0].offsetWidth + 'px').css('height', elem[0].offsetHeight + 'px') .css('position', 'absolute').css('top', '0px').css('left', '0px'); } } }; elem.bind('mouseenter', fixInputStyle); var fileApiChangeFn = function (evt) { var files = FileAPI.getFiles(evt); //just a double check for #233 for (var i = 0; i < files.length; i++) { if (files[i].size === undefined) files[i].size = 0; if (files[i].name === undefined) files[i].name = 'file'; if (files[i].type === undefined) files[i].type = 'undefined'; } if (!evt.target) { evt.target = {}; } evt.target.files = files; // if evt.target.files is not writable use helper field if (evt.target.files !== files) { evt.__files_ = files; } (evt.__files_ || evt.target.files).item = function (i) { return (evt.__files_ || evt.target.files)[i] || null; }; }; }; FileAPI.disableFileInput = function (elem, disable) { if (disable) { elem.removeClass('js-fileapi-wrapper'); } else { elem.addClass('js-fileapi-wrapper'); } }; } })(); if (!window.FileReader) { window.FileReader = function () { var _this = this, loadStarted = false; this.listeners = {}; this.addEventListener = function (type, fn) { _this.listeners[type] = _this.listeners[type] || []; _this.listeners[type].push(fn); }; this.removeEventListener = function (type, fn) { if (_this.listeners[type]) _this.listeners[type].splice(_this.listeners[type].indexOf(fn), 1); }; this.dispatchEvent = function (evt) { var list = _this.listeners[evt.type]; if (list) { for (var i = 0; i < list.length; i++) { list[i].call(_this, evt); } } }; this.onabort = this.onerror = this.onload = this.onloadstart = this.onloadend = this.onprogress = null; var constructEvent = function (type, evt) { var e = {type: type, target: _this, loaded: evt.loaded, total: evt.total, error: evt.error}; if (evt.result != null) e.target.result = evt.result; return e; }; var listener = function (evt) { if (!loadStarted) { loadStarted = true; if (_this.onloadstart) _this.onloadstart(constructEvent('loadstart', evt)); } var e; if (evt.type === 'load') { if (_this.onloadend) _this.onloadend(constructEvent('loadend', evt)); e = constructEvent('load', evt); if (_this.onload) _this.onload(e); _this.dispatchEvent(e); } else if (evt.type === 'progress') { e = constructEvent('progress', evt); if (_this.onprogress) _this.onprogress(e); _this.dispatchEvent(e); } else { e = constructEvent('error', evt); if (_this.onerror) _this.onerror(e); _this.dispatchEvent(e); } }; this.readAsDataURL = function (file) { FileAPI.readAsDataURL(file, listener); }; this.readAsText = function (file) { FileAPI.readAsText(file, listener); }; }; }