/*
* dmuploader.js - Jquery File Uploader - 0.1
* http://www.daniel.com.uy/projects/jquery-file-uploader/
*
* Copyright (c) 2013 Daniel Morales
* Dual licensed under the MIT and GPL licenses.
* http://www.daniel.com.uy/doc/license/
*/
(function($) {
var pluginName = 'dmUploader';
// These are the plugin defaults values
var defaults = {
url: document.URL,
method: 'POST',
extraData: {},
maxFileSize: 0,
maxFiles: 0,
allowedTypes: '*',
extFilter: null,
dataType: null,
fileName: 'file',
onInit: function(){},
onFallbackMode: function(message) {},
onNewFile: function(id, file){},
onBeforeUpload: function(id){},
onComplete: function(){},
onUploadProgress: function(id, percent){},
onUploadSuccess: function(id, data){},
onUploadError: function(id, message){},
onFileTypeError: function(file){},
onFileSizeError: function(file){},
onFileExtError: function(file){},
onFilesMaxError: function(file){}
};
var DmUploader = function(element, options)
{
this.element = $(element);
this.settings = $.extend({}, defaults, options);
if(!this.checkBrowser()){
return false;
}
this.init();
return true;
};
DmUploader.prototype.checkBrowser = function()
{
if(window.FormData === undefined){
this.settings.onFallbackMode.call(this.element, 'Browser doesn\'t support Form API');
return false;
}
if(this.element.find('input[type=file]').length > 0){
return true;
}
if (!this.checkEvent('drop', this.element) || !this.checkEvent('dragstart', this.element)){
this.settings.onFallbackMode.call(this.element, 'Browser doesn\'t support Ajax Drag and Drop');
return false;
}
return true;
};
DmUploader.prototype.checkEvent = function(eventName, element)
{
var element = element || document.createElement('div');
var eventName = 'on' + eventName;
var isSupported = eventName in element;
if(!isSupported){
if(!element.setAttribute){
element = document.createElement('div');
}
if(element.setAttribute && element.removeAttribute){
element.setAttribute(eventName, '');
isSupported = typeof element[eventName] == 'function';
if(typeof element[eventName] != 'undefined'){
element[eventName] = undefined;
}
element.removeAttribute(eventName);
}
}
element = null;
return isSupported;
};
DmUploader.prototype.init = function()
{
var widget = this;
widget.queue = new Array();
widget.queuePos = -1;
widget.queueRunning = false;
// -- Drag and drop event
widget.element.on('drop', function (evt){
evt.preventDefault();
var files = evt.originalEvent.dataTransfer.files;
widget.queueFiles(files);
});
//-- Optional File input to make a clickable area
widget.element.find('input[type=file]').on('change', function(evt){
var files = evt.target.files;
widget.queueFiles(files);
$(this).val('');
});
this.settings.onInit.call(this.element);
};
DmUploader.prototype.queueFiles = function(files)
{
var j = this.queue.length;
for (var i= 0; i < files.length; i++)
{
var file = files[i];
// Check file size
if((this.settings.maxFileSize > 0) &&
(file.size > this.settings.maxFileSize)){
this.settings.onFileSizeError.call(this.element, file);
continue;
}
// Check file type
if((this.settings.allowedTypes != '*') &&
!file.type.match(this.settings.allowedTypes)){
this.settings.onFileTypeError.call(this.element, file);
continue;
}
// Check file extension
if(this.settings.extFilter != null){
var extList = this.settings.extFilter.toLowerCase().split(';');
var ext = file.name.toLowerCase().split('.').pop();
if($.inArray(ext, extList) < 0){
this.settings.onFileExtError.call(this.element, file);
continue;
}
}
// Check max files
if(this.settings.maxFiles > 0) {
if(this.queue.length >= this.settings.maxFiles) {
this.settings.onFilesMaxError.call(this.element, file);
continue;
}
}
this.queue.push(file);
var index = this.queue.length - 1;
this.settings.onNewFile.call(this.element, index, file);
}
// Only start Queue if we haven't!
if(this.queueRunning){
return false;
}
// and only if new Failes were successfully added
if(this.queue.length == j){
return false;
}
this.processQueue();
return true;
};
DmUploader.prototype.processQueue = function()
{
var widget = this;
widget.queuePos++;
if(widget.queuePos >= widget.queue.length){
// Cleanup
widget.settings.onComplete.call(widget.element);
// Wait until new files are droped
widget.queuePos = (widget.queue.length - 1);
widget.queueRunning = false;
return;
}
var file = widget.queue[widget.queuePos];
// Form Data
var fd = new FormData();
fd.append(widget.settings.fileName, file);
// Return from client function (default === undefined)
var can_continue = widget.settings.onBeforeUpload.call(widget.element, widget.queuePos);
// If the client function doesn't return FALSE then continue
if( false === can_continue ) {
return;
}
// Append extra Form Data
$.each(widget.settings.extraData, function(exKey, exVal){
fd.append(exKey, exVal);
});
widget.queueRunning = true;
// Ajax Submit
$.ajax({
url: widget.settings.url,
type: widget.settings.method,
dataType: widget.settings.dataType,
data: fd,
cache: false,
contentType: false,
processData: false,
forceSync: false,
xhr: function(){
var xhrobj = $.ajaxSettings.xhr();
if(xhrobj.upload){
xhrobj.upload.addEventListener('progress', function(event) {
var percent = 0;
var position = event.loaded || event.position;
var total = event.total || event.totalSize;
if(event.lengthComputable){
percent = Math.ceil(position / total * 100);
}
widget.settings.onUploadProgress.call(widget.element, widget.queuePos, percent);
}, false);
}
return xhrobj;
},
success: function (data, message, xhr){
widget.settings.onUploadSuccess.call(widget.element, widget.queuePos, data);
},
error: function (xhr, status, errMsg){
widget.settings.onUploadError.call(widget.element, widget.queuePos, errMsg);
},
complete: function(xhr, textStatus){
widget.processQueue();
}
});
}
$.fn.dmUploader = function(options){
return this.each(function(){
if(!$.data(this, pluginName)){
$.data(this, pluginName, new DmUploader(this, options));
}
});
};
// -- Disable Document D&D events to prevent opening the file on browser when we drop them
$(document).on('dragenter', function (e) { e.stopPropagation(); e.preventDefault(); });
$(document).on('dragover', function (e) { e.stopPropagation(); e.preventDefault(); });
$(document).on('drop', function (e) { e.stopPropagation(); e.preventDefault(); });
})(jQuery);
|