mirror of https://github.com/gophish/gophish
300 lines
8.4 KiB
JavaScript
300 lines
8.4 KiB
JavaScript
|
/**!
|
||
|
* 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);
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
} ]);
|
||
|
|
||
|
})();
|