123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- /**!
- * 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 <danial.farid@gmail.com>
- * @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);
- };
- };
- }
|