/* ----------------------------------------------------------------------------
// Ezdz [izy-dizy]
// v0.4.0 - released 2013-10-22 14:08
// Licensed under the MIT license.
// https://github.com/jaysalvat/ezdz
// ----------------------------------------------------------------------------
// Copyright (C) 2013 Jay Salvat
// http://jaysalvat.com/
// ---------------------------------------------------------------------------*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(['jquery'], factory);
} else if (typeof exports === 'object') {
factory(require('jquery'));
} else {
factory(jQuery);
}
}(function ($) {
// Default settings
var defaults = {
className: '',
text: 'Drop a file',
previewImage: true,
value: null,
classes: {
main: 'ezdz-dropzone',
enter: 'ezdz-enter',
reject: 'ezdz-reject',
accept: 'ezdz-accept',
focus: 'ezdz-focus'
},
validators: {
maxSize: null,
width: null,
maxWidth: null,
minWidth: null,
height: null,
maxHeight: null,
minHeight: null
},
init: function() {},
enter: function() {},
leave: function() {},
reject: function() {},
accept: function() {},
format: function(filename) {
return filename;
}
};
// Main plugin
$.ezdz = function(element, options) {
this.settings = $.extend(true, {}, defaults, $.ezdz.defaults, options);
this.$input = $(element);
var self = this,
settings = self.settings,
$input = self.$input;
if (!$input.is('input[type="file"]')) {
return;
}
// Stop if not compatible with HTML5 file API
if (!$.ezdz.isBrowserCompatible()) {
return;
}
// private: Init the plugin
var init = function() {
var $ezdz, $container, value;
// Build the container
$container = $('
')
.on('dragover.ezdz', function() {
$(this).addClass(settings.classes.enter);
if ($.isFunction(settings.enter)) {
settings.enter.apply(this);
}
})
.on('dragleave.ezdz', function() {
$(this).removeClass(settings.classes.enter);
if ($.isFunction(settings.leaved)) {
settings.leaved.apply(this);
}
})
.addClass(settings.className);
// Build the whole dropzone
$input
.wrap($container)
.before('' + settings.text + '
');
$ezdz = $input.parent('.' + settings.classes.main);
// Preview a file at start if it's defined
value = settings.value || $input.data('value');
if (value) {
self.preview(value);
}
// Trigger the init callback
if ($.isFunction(settings.init)) {
settings.init.apply($input, [ value ]);
}
// Events on the input
$input
.on('focus.ezdz', function() {
$ezdz.addClass(settings.classes.focus);
})
.on('blur.ezdz', function() {
$ezdz.removeClass(settings.classes.focus);
})
.on('change.ezdz', function() {
var file = this.files[0];
// No file, so user has cancelled
if (!file) {
return;
}
// Info about the dropped or selected file
var basename = file.name.replace(/\\/g,'/').replace( /.*\//, ''),
extension = file.name.split('.').pop(),
formatted = settings.format(basename);
file.extension = extension;
// Mime-Types
var allowed = $input.attr('accept'),
accepted = false;
valid = true;
errors = {
'mimeType': false,
'maxSize': false,
'width': false,
'minWidth': false,
'maxWidth': false,
'height': false,
'minHeight': false,
'maxHeight': false
};
// Check the accepted Mime-Types from the input file
if (allowed) {
var types = allowed.split(/[,|]/);
$.each(types, function(i, type) {
type = $.trim(type);
if (file.type == type) {
accepted = true;
return false;
}
// Mime-Type with wildcards ex. image/*
if (type.indexOf('/*') !== false) {
var a = type.replace('/*', ''),
b = file.type.replace(/(\/.*)$/g, '');
if (a === b) {
accepted = true;
return false;
}
}
});
if (accepted === false) {
errors.mimeType = true;
}
} else {
accepted = true;
}
// Reset the accepted / rejected classes
$ezdz.removeClass(settings.classes.reject + ' ' + settings.classes.accept);
// If the Mime-Type is not accepted
if (accepted !== true) {
$input.val('');
$ezdz.addClass(settings.classes.reject);
// Trigger the reject callback
if ($.isFunction(settings.reject)) {
settings.reject.apply($input, [ file, errors ]);
}
return false;
}
// Read the added file
var reader = new FileReader(file);
reader.readAsDataURL(file);
reader.onload = function(e) {
var img = new Image(),
isImage;
file.data = e.target.result;
img.src = file.data;
setTimeout(function() {
isImage = (img.width && img.height);
// Validator
if (settings.validators.maxSize && file.size > settings.validators.maxSize) {
valid = false;
errors.maxSize = true;
}
if (isImage) {
file.width = img.width;
file.height = img.height;
if (settings.validators.width && img.width != settings.validators.width) {
valid = false;
errors.width = true;
}
if (settings.validators.maxWidth && img.width > settings.validators.maxWidth) {
valid = false;
errors.maxWidth = true;
}
if (settings.validators.minWidth && img.width < settings.validators.minWidth) {
valid = false;
errors.minWidth = true;
}
if (settings.validators.height && img.height != settings.validators.height) {
valid = false;
errors.height = true;
}
if (settings.validators.maxHeight && img.height > settings.validators.maxHeight) {
valid = false;
errors.maxHeight = true;
}
if (settings.validators.minHeight && img.height < settings.validators.minHeight) {
valid = false;
errors.minHeight = true;
}
}
// The file is validated, so added to input
if (valid === true) {
$ezdz.find('img').remove();
if (isImage && settings.previewImage === true) {
$ezdz.find('div').html($(img).fadeIn());
} else {
$ezdz.find('div').html('' + formatted + '');
}
$ezdz.addClass(settings.classes.accept);
// Trigger the accept callback
if ($.isFunction(settings.accept)) {
settings.accept.apply($input, [ file ]);
}
// The file is invalidated, so rejected
} else {
$input.val('');
$ezdz.addClass(settings.classes.reject);
// Trigger the reject callback
if ($.isFunction(settings.reject)) {
settings.reject.apply($input, [ file, errors ]);
}
}
}, 250);
};
});
};
init();
};
// Inject a file or image in the preview
$.ezdz.prototype.preview = function(path, callback) {
var settings = this.settings,
$input = this.$input,
$ezdz = $input.parent('.' + settings.classes.main);
basename = path.replace(/\\/g,'/').replace( /.*\//, ''),
formatted = settings.format(basename);
var img = new Image();
img.src = path;
// Is an image
img.onload = function() {
$ezdz.find('div').html($(img).fadeIn());
if ($.isFunction(callback)) {
callback.apply(this);
}
};
// Is not an image
img.onerror = function() {
$ezdz.find('div').html('' + formatted + '');
if ($.isFunction(callback)) {
callback.apply(this);
}
};
$ezdz.addClass(settings.classes.accept);
};
// Destroy ezdz
$.ezdz.prototype.destroy = function() {
var settings = this.settings,
$input = this.$input;
$input.parent('.' + settings.classes.main).replaceWith($input);
$input.off('*.ezdz');
$input.data('ezdz', '');
};
// Extend settings
$.ezdz.prototype.options = function(options) {
var settings = this.settings;
if (!options) {
return settings;
}
$.extend(true, this.settings, options);
};
// Get input container
$.ezdz.prototype.container = function() {
var settings = this.settings,
$input = this.$input;
return $input.parent('.' + settings.classes.main);
};
// Is browser compatible
$.ezdz.isBrowserCompatible = function() {
return !!(window.File && window.FileList && window.FileReader);
};
// Default options
$.ezdz.defaults = defaults;
// jQuery plugin
$.fn.ezdz = function(options) {
var args = arguments,
plugin = $(this).data('ezdz');
if (!plugin) {
return $(this).data('ezdz', new $.ezdz(this, options));
} if (plugin[options]) {
return plugin[options].apply(plugin, Array.prototype.slice.call(args, 1));
} else {
$.error('Ezdz error - Method ' + options + ' does not exist.');
}
};
}));