gophish/static/js/angular-file-upload.js

300 lines
8.4 KiB
JavaScript
Raw Normal View History

2014-07-12 18:43:14 +00:00
/**!
* AngularJS file upload/drop directive with http post and progress
* @author Danial <danial.farid@gmail.com>
* @version 1.5.0
*/
(function() {
var angularFileUpload = angular.module('angularFileUpload', []);
angularFileUpload.service('$upload', ['$http', '$q', '$timeout', function($http, $q, $timeout) {
function sendHttp(config) {
config.method = config.method || 'POST';
config.headers = config.headers || {};
config.transformRequest = config.transformRequest || function(data, headersGetter) {
if (window.ArrayBuffer && data instanceof window.ArrayBuffer) {
return data;
}
console.log($http.defaults.transformRequest[0])
console.log($http.defaults.transformRequest[0](data, headersGetter))
return $http.defaults.transformRequest[0](data, headersGetter);
};
var deferred = $q.defer();
if (window.XMLHttpRequest.__isShim) {
config.headers['__setXHR_'] = function() {
return function(xhr) {
if (!xhr) return;
config.__XHR = xhr;
config.xhrFn && config.xhrFn(xhr);
xhr.upload.addEventListener('progress', function(e) {
deferred.notify(e);
}, false);
//fix for firefox not firing upload progress end, also IE8-9
xhr.upload.addEventListener('load', function(e) {
if (e.lengthComputable) {
deferred.notify(e);
}
}, false);
};
};
}
$http(config).then(function(r){deferred.resolve(r)}, function(e){deferred.reject(e)}, function(n){deferred.notify(n)});
var promise = deferred.promise;
promise.success = function(fn) {
promise.then(function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
promise.error = function(fn) {
promise.then(null, function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
promise.progress = function(fn) {
promise.then(null, null, function(update) {
fn(update);
});
return promise;
};
promise.abort = function() {
if (config.__XHR) {
$timeout(function() {
config.__XHR.abort();
});
}
return promise;
};
promise.xhr = function(fn) {
config.xhrFn = (function(origXhrFn) {
return function() {
origXhrFn && origXhrFn.apply(promise, arguments);
fn.apply(promise, arguments);
}
})(config.xhrFn);
return promise;
};
return promise;
}
this.upload = function(config) {
config.headers = config.headers || {};
config.headers['Content-Type'] = undefined;
config.transformRequest = config.transformRequest || $http.defaults.transformRequest;
var formData = new FormData();
var origTransformRequest = config.transformRequest;
var origData = config.data;
config.transformRequest = function(formData, headerGetter) {
if (origData) {
if (config.formDataAppender) {
for (var key in origData) {
var val = origData[key];
config.formDataAppender(formData, key, val);
}
} else {
for (var key in origData) {
var val = origData[key];
if (typeof origTransformRequest == 'function') {
val = origTransformRequest(val, headerGetter);
} else {
for (var i = 0; i < origTransformRequest.length; i++) {
var transformFn = origTransformRequest[i];
if (typeof transformFn == 'function') {
val = transformFn(val, headerGetter);
}
}
}
formData.append(key, val);
}
}
}
if (config.file != null) {
var fileFormName = config.fileFormDataName || 'file';
if (Object.prototype.toString.call(config.file) === '[object Array]') {
var isFileFormNameString = Object.prototype.toString.call(fileFormName) === '[object String]';
for (var i = 0; i < config.file.length; i++) {
formData.append(isFileFormNameString ? fileFormName : fileFormName[i], config.file[i],
(config.fileName && config.fileName[i]) || config.file[i].name);
}
} else {
formData.append(fileFormName, config.file, config.fileName || config.file.name);
}
}
return formData;
};
config.data = formData;
return sendHttp(config);
};
this.http = function(config) {
return sendHttp(config);
}
}]);
angularFileUpload.directive('ngFileSelect', [ '$parse', '$timeout', function($parse, $timeout) {
return function(scope, elem, attr) {
var fn = $parse(attr['ngFileSelect']);
elem.bind('change', function(evt) {
var files = [], fileList, i;
fileList = evt.target.files;
if (fileList != null) {
for (i = 0; i < fileList.length; i++) {
files.push(fileList.item(i));
}
}
$timeout(function() {
fn(scope, {
$files : files,
$event : evt
});
});
});
// removed this since it was confusing if the user click on browse and then cancel #181
// elem.bind('click', function(){
// this.value = null;
// });
// touch screens
if (('ontouchstart' in window) ||
(navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)) {
elem.bind('touchend', function(e) {
e.preventDefault();
e.target.click();
});
}
};
} ]);
angularFileUpload.directive('ngFileDropAvailable', [ '$parse', '$timeout', function($parse, $timeout) {
return function(scope, elem, attr) {
if ('draggable' in document.createElement('span')) {
var fn = $parse(attr['ngFileDropAvailable']);
$timeout(function() {
fn(scope);
});
}
};
} ]);
angularFileUpload.directive('ngFileDrop', [ '$parse', '$timeout', '$location', function($parse, $timeout, $location) {
return function(scope, elem, attr) {
if ('draggable' in document.createElement('span')) {
var leaveTimeout = null;
elem[0].addEventListener("dragover", function(evt) {
evt.stopPropagation();
evt.preventDefault();
elem.addClass(elem[0].__drag_over_class_);
$timeout.cancel(leaveTimeout);
if (!elem[0].__drag_entered_) {
elem[0].__drag_entered_ = true;
var dragOverClassFn = $parse(attr['ngFileDragOverClass']);
if (dragOverClassFn instanceof Function) {
var dragOverClass = dragOverClassFn(scope, {
$event : evt
});
elem[0].__drag_over_class_ = dragOverClass;
elem.addClass(elem[0].__drag_over_class_);
} else {
elem[0].__drag_over_class_ = attr['ngFileDragOverClass'] || "dragover";
elem.addClass(elem[0].__drag_over_class_);
}
}
}, false);
elem[0].addEventListener("dragenter", function(evt) {
evt.stopPropagation();
evt.preventDefault();
}, false);
elem[0].addEventListener("dragleave", function(evt) {
leaveTimeout = $timeout(function() {
elem[0].__drag_entered_ = false;
elem.removeClass(elem[0].__drag_over_class_);
});
}, false);
var fn = $parse(attr['ngFileDrop']);
elem[0].addEventListener("drop", function(evt) {
evt.stopPropagation();
evt.preventDefault();
elem[0].__drag_entered_ = false;
elem.removeClass(elem[0].__drag_over_class_);
extractFiles(evt, function(files) {
fn(scope, {
$files : files,
$event : evt
});
});
}, false);
function isASCII(str) {
return /^[\000-\177]*$/.test(str);
}
function extractFiles(evt, callback) {
var files = [], items = evt.dataTransfer.items;
if (items && items.length > 0 && items[0].webkitGetAsEntry && $location.protocol() != 'file') {
for (var i = 0; i < items.length; i++) {
var entry = items[i].webkitGetAsEntry();
if (entry != null) {
//fix for chrome bug https://code.google.com/p/chromium/issues/detail?id=149735
if (isASCII(entry.name)) {
traverseFileTree(files, entry);
} else {
files.push(items[i].getAsFile());
}
}
}
} else {
var fileList = evt.dataTransfer.files;
if (fileList != null) {
for (var i = 0; i < fileList.length; i++) {
files.push(fileList.item(i));
}
}
}
(function waitForProcess(delay) {
$timeout(function() {
if (!processing) {
callback(files);
} else {
waitForProcess(10);
}
}, delay || 0)
})();
}
var processing = 0;
function traverseFileTree(files, entry) {
if (entry != null) {
if (entry.isDirectory) {
var dirReader = entry.createReader();
processing++;
dirReader.readEntries(function(entries) {
for (var i = 0; i < entries.length; i++) {
traverseFileTree(files, entries[i]);
}
processing--;
});
} else {
processing++;
entry.file(function(file) {
processing--;
files.push(file);
});
}
}
}
}
};
} ]);
})();