metro4
Version:
The front-end framework for Build responsive, mobile-first projects on the web with the first front-end component library in Metro Style
200 lines (163 loc) • 6.1 kB
JavaScript
var File = {
init: function( options, elem ) {
this.options = $.extend( {}, this.options, options );
this.elem = elem;
this.element = $(elem);
this._setOptionsFromDOM();
this._create();
Utils.exec(this.options.onFileCreate, [this.element], elem);
return this;
},
options: {
mode: "input",
buttonTitle: "Choose file(s)",
filesTitle: "file(s) selected",
dropTitle: "<strong>Choose a file</strong> or drop it here",
dropIcon: "<span class='default-icon-upload'></span>",
prepend: "",
clsComponent: "",
clsPrepend: "",
clsButton: "",
clsCaption: "",
copyInlineStyles: true,
onSelect: Metro.noop,
onFileCreate: Metro.noop
},
_setOptionsFromDOM: function(){
var element = this.element, o = this.options;
$.each(element.data(), function(key, value){
if (key in o) {
try {
o[key] = JSON.parse(value);
} catch (e) {
o[key] = value;
}
}
});
},
_create: function(){
this._createStructure();
this._createEvents();
},
_createStructure: function(){
var element = this.element, o = this.options;
var container = $("<label>").addClass((o.mode === "input" ? " file " : " drop-zone ") + element[0].className).addClass(o.clsComponent);
var caption = $("<span>").addClass("caption").addClass(o.clsCaption);
var files = $("<span>").addClass("files").addClass(o.clsCaption);
var icon, button;
container.insertBefore(element);
element.appendTo(container);
if (o.mode === "input") {
caption.insertBefore(element);
button = $("<button>").addClass("button").attr("tabindex", -1).attr("type", "button").html(o.buttonTitle);
button.appendTo(container);
button.addClass(o.clsButton);
if (element.attr('dir') === 'rtl' ) {
container.addClass("rtl");
}
if (o.prepend !== "") {
var prepend = $("<div>").html(o.prepend);
prepend.addClass("prepend").addClass(o.clsPrepend).appendTo(container);
}
} else {
icon = $(o.dropIcon).addClass("icon").appendTo(container);
caption.html(o.dropTitle).insertAfter(icon);
files.html("0" + " " + o.filesTitle).insertAfter(caption);
}
element[0].className = '';
if (o.copyInlineStyles === true) {
for (var i = 0, l = element[0].style.length; i < l; i++) {
container.css(element[0].style[i], element.css(element[0].style[i]));
}
}
if (element.is(":disabled")) {
this.disable();
} else {
this.enable();
}
},
_createEvents: function(){
var element = this.element, o = this.options;
var container = element.closest("label");
var caption = container.find(".caption");
var files = container.find(".files");
container.on(Metro.events.click, "button", function(){
element.trigger("click");
});
element.on(Metro.events.change, function(){
var fi = this;
var file_names = [];
var entry;
if (fi.files.length === 0) {
return ;
}
Array.from(fi.files).forEach(function(file){
file_names.push(file.name);
});
if (o.mode === "input") {
entry = file_names.join(", ");
caption.html(entry);
caption.attr('title', entry);
} else {
files.html(element[0].files.length + " " +o.filesTitle);
}
Utils.exec(o.onSelect, [fi.files, element], element[0]);
});
element.on(Metro.events.focus, function(){container.addClass("focused");});
element.on(Metro.events.blur, function(){container.removeClass("focused");});
if (o.mode !== "input") {
container.on('drag dragstart dragend dragover dragenter dragleave drop', function(e){
e.preventDefault();
});
container.on('dragenter dragover', function(){
container.addClass("drop-on");
});
container.on('dragleave', function(){
container.removeClass("drop-on");
});
container.on('drop', function(e){
element[0].files = e.originalEvent.dataTransfer.files;
files.html(element[0].files.length + " " +o.filesTitle);
container.removeClass("drop-on");
if (!Utils.detectChrome()) Utils.exec(o.onSelect, [element[0].files, element], element[0]);
});
}
},
disable: function(){
this.element.data("disabled", true);
this.element.parent().addClass("disabled");
},
enable: function(){
this.element.data("disabled", false);
this.element.parent().removeClass("disabled");
},
toggleState: function(){
if (this.elem.disabled) {
this.disable();
} else {
this.enable();
}
},
toggleDir: function(){
if (this.element.attr("dir") === 'rtl') {
this.element.parent().addClass("rtl");
} else {
this.element.parent().removeClass("rtl");
}
},
changeAttribute: function(attributeName){
switch (attributeName) {
case 'disabled': this.toggleState(); break;
case 'dir': this.toggleDir(); break;
}
},
destroy: function(){
var element = this.element;
var parent = element.parent();
element.off(Metro.events.change);
parent.off(Metro.events.click, "button");
element.insertBefore(parent);
parent.remove();
}
};
Metro.plugin('file', File);