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
421 lines (352 loc) • 13.8 kB
JavaScript
var Input = {
init: function( options, elem ) {
this.options = $.extend( {}, this.options, options );
this.elem = elem;
this.element = $(elem);
this.history = [];
this.historyIndex = -1;
this.autocomplete = [];
this._setOptionsFromDOM();
this._create();
Utils.exec(this.options.onInputCreate, [this.element], this.elem);
return this;
},
options: {
autocomplete: null,
autocompleteDivider: ",",
autocompleteListHeight: 200,
history: false,
historyPreset: "",
historyDivider: "|",
preventSubmit: false,
defaultValue: "",
size: "default",
prepend: "",
append: "",
copyInlineStyles: true,
searchButton: false,
clearButton: true,
revealButton: true,
clearButtonIcon: "<span class='default-icon-cross'></span>",
revealButtonIcon: "<span class='default-icon-eye'></span>",
searchButtonIcon: "<span class='default-icon-search'></span>",
customButtons: [],
searchButtonClick: 'submit',
clsComponent: "",
clsInput: "",
clsPrepend: "",
clsAppend: "",
clsClearButton: "",
clsRevealButton: "",
clsCustomButton: "",
clsSearchButton: "",
onHistoryChange: Metro.noop,
onHistoryUp: Metro.noop,
onHistoryDown: Metro.noop,
onClearClick: Metro.noop,
onRevealClick: Metro.noop,
onSearchButtonClick: Metro.noop,
onEnterClick: Metro.noop,
onInputCreate: 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 that = this, element = this.element, o = this.options;
var prev = element.prev();
var parent = element.parent();
var container = $("<div>").addClass("input " + element[0].className);
var buttons = $("<div>").addClass("button-group");
var clearButton, revealButton, searchButton;
if (Utils.isValue(o.historyPreset)) {
$.each(Utils.strToArray(o.historyPreset, o.historyDivider), function(){
that.history.push(this);
});
that.historyIndex = that.history.length - 1;
}
if (element.attr("type") === undefined) {
element.attr("type", "text");
}
if (prev.length === 0) {
parent.prepend(container);
} else {
container.insertAfter(prev);
}
element.appendTo(container);
buttons.appendTo(container);
if (!Utils.isValue(element.val().trim())) {
element.val(o.defaultValue);
}
if (o.clearButton === true) {
clearButton = $("<button>").addClass("button input-clear-button").addClass(o.clsClearButton).attr("tabindex", -1).attr("type", "button").html(o.clearButtonIcon);
clearButton.appendTo(buttons);
}
if (element.attr('type') === 'password' && o.revealButton === true) {
revealButton = $("<button>").addClass("button input-reveal-button").addClass(o.clsRevealButton).attr("tabindex", -1).attr("type", "button").html(o.revealButtonIcon);
revealButton.appendTo(buttons);
}
if (o.searchButton === true) {
searchButton = $("<button>").addClass("button input-search-button").addClass(o.clsSearchButton).attr("tabindex", -1).attr("type", o.searchButtonClick === 'submit' ? "submit" : "button").html(o.searchButtonIcon);
searchButton.appendTo(buttons);
}
if (o.prepend !== "") {
var prepend = $("<div>").html(o.prepend);
prepend.addClass("prepend").addClass(o.clsPrepend).appendTo(container);
}
if (o.append !== "") {
var append = $("<div>").html(o.append);
append.addClass("append").addClass(o.clsAppend).appendTo(container);
}
if (typeof o.customButtons === "string") {
o.customButtons = Utils.isObject(o.customButtons);
}
if (typeof o.customButtons === "object" && Utils.objectLength(o.customButtons) > 0) {
$.each(o.customButtons, function(){
var item = this;
var customButton = $("<button>");
customButton
.addClass("button input-custom-button")
.addClass(o.clsCustomButton)
.addClass(item.cls)
.attr("tabindex", -1)
.attr("type", "button")
.html(item.html);
customButton.data("action", item.onclick);
customButton.appendTo(buttons);
});
}
if (element.attr('dir') === 'rtl' ) {
container.addClass("rtl").attr("dir", "rtl");
}
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]));
}
}
container.addClass(o.clsComponent);
element.addClass(o.clsInput);
if (o.size !== "default") {
container.css({
width: o.size
});
}
if (!Utils.isNull(o.autocomplete)) {
var autocomplete_obj = Utils.isObject(o.autocomplete);
if (autocomplete_obj !== false) {
that.autocomplete = autocomplete_obj;
} else {
this.autocomplete = Utils.strToArray(o.autocomplete, o.autocompleteDivider);
}
$("<div>").addClass("autocomplete-list").css({
maxHeight: o.autocompleteListHeight,
display: "none"
}).appendTo(container);
}
if (element.is(":disabled")) {
this.disable();
} else {
this.enable();
}
},
_createEvents: function(){
var that = this, element = this.element, o = this.options;
var container = element.closest(".input");
var autocompleteList = container.find(".autocomplete-list");
container.on(Metro.events.click, ".input-clear-button", function(){
var curr = element.val();
element.val(Utils.isValue(o.defaultValue) ? o.defaultValue : "").trigger('change').trigger('keyup').focus();
if (autocompleteList.length > 0) {
autocompleteList.css({
display: "none"
})
}
Utils.exec(o.onClearClick, [curr, element.val()], element[0]);
});
container.on(Metro.events.start, ".input-reveal-button", function(){
element.attr('type', 'text');
Utils.exec(o.onRevealClick, [element.val()], element[0]);
});
container.on(Metro.events.start, ".input-search-button", function(){
if (o.searchButtonClick !== 'submit') {
Utils.exec(o.onSearchButtonClick, [element.val(), $(this)], element[0]);
} else {
this.form.submit();
}
});
container.on(Metro.events.stop, ".input-reveal-button", function(){
element.attr('type', 'password').focus();
});
container.on(Metro.events.stop, ".input-custom-button", function(){
var button = $(this);
var action = button.data("action");
Utils.exec(action, [element.val(), button], this);
});
element.on(Metro.events.keyup, function(e){
var val = element.val().trim();
if (o.history && e.keyCode === Metro.keyCode.ENTER && val !== "") {
element.val("");
that.history.push(val);
that.historyIndex = that.history.length - 1;
Utils.exec(o.onHistoryChange, [val, that.history, that.historyIndex], element[0]);
if (o.preventSubmit === true) {
e.preventDefault();
}
}
if (o.history && e.keyCode === Metro.keyCode.UP_ARROW) {
that.historyIndex--;
if (that.historyIndex >= 0) {
element.val("");
element.val(that.history[that.historyIndex]);
Utils.exec(o.onHistoryDown, [element.val(), that.history, that.historyIndex], element[0]);
} else {
that.historyIndex = 0;
}
e.preventDefault();
}
if (o.history && e.keyCode === Metro.keyCode.DOWN_ARROW) {
that.historyIndex++;
if (that.historyIndex < that.history.length) {
element.val("");
element.val(that.history[that.historyIndex]);
Utils.exec(o.onHistoryUp, [element.val(), that.history, that.historyIndex], element[0]);
} else {
that.historyIndex = that.history.length - 1;
}
e.preventDefault();
}
});
element.on(Metro.events.keydown, function(e){
if (e.keyCode === Metro.keyCode.ENTER) {
Utils.exec(o.onEnterClick, [element.val()], element[0]);
}
});
element.on(Metro.events.blur, function(){
container.removeClass("focused");
});
element.on(Metro.events.focus, function(){
container.addClass("focused");
});
element.on(Metro.events.input, function(){
var val = this.value.toLowerCase();
var items;
if (autocompleteList.length === 0) {
return;
}
autocompleteList.html("");
items = that.autocomplete.filter(function(item){
return item.toLowerCase().indexOf(val) > -1;
});
autocompleteList.css({
display: items.length > 0 ? "block" : "none"
});
$.each(items, function(i, v){
var index = v.toLowerCase().indexOf(val);
var item = $("<div>").addClass("item").attr("data-autocomplete-value", v);
var html;
if (index === 0) {
html = "<strong>"+v.substr(0, val.length)+"</strong>"+v.substr(val.length);
} else {
html = v.substr(0, index) + "<strong>"+v.substr(index, val.length)+"</strong>"+v.substr(index + val.length);
}
item.html(html).appendTo(autocompleteList);
})
});
container.on(Metro.events.click, ".autocomplete-list .item", function(){
element.val($(this).attr("data-autocomplete-value"));
autocompleteList.css({
display: "none"
});
element.trigger("change");
});
},
getHistory: function(){
return this.history;
},
getHistoryIndex: function(){
return this.historyIndex;
},
setHistoryIndex: function(val){
this.historyIndex = val >= this.history.length ? this.history.length - 1 : val;
},
setHistory: function(history, append) {
var that = this, o = this.options;
if (Utils.isNull(history)) return;
if (!Array.isArray(history)) {
history = Utils.strToArray(history, o.historyDivider);
}
if (append === true) {
$.each(history, function () {
that.history.push(this);
})
} else{
this.history = history;
}
this.historyIndex = this.history.length - 1;
},
clear: function(){
this.element.val('');
},
toDefault: function(){
this.element.val(Utils.isValue(this.options.defaultValue) ? this.options.defaultValue : "");
},
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();
}
},
changeAttribute: function(attributeName){
switch (attributeName) {
case 'disabled': this.toggleState(); break;
}
},
destroy: function(){
var element = this.element;
var parent = element.parent();
var clearBtn = parent.find(".input-clear-button");
var revealBtn = parent.find(".input-reveal-button");
var customBtn = parent.find(".input-custom-button");
if (clearBtn.length > 0) {
clearBtn.off(Metro.events.click);
}
if (revealBtn.length > 0) {
revealBtn.off(Metro.events.start);
revealBtn.off(Metro.events.stop);
}
if (customBtn.length > 0) {
clearBtn.off(Metro.events.click);
}
element.off(Metro.events.blur);
element.off(Metro.events.focus);
element.insertBefore(parent);
parent.remove();
}
};
Metro.plugin('input', Input);
$(document).on(Metro.events.click, function(e){
$('.input .autocomplete-list').hide();
});