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
378 lines (313 loc) • 11.1 kB
JavaScript
var Keypad = {
init: function( options, elem ) {
this.options = $.extend( {}, this.options, options );
this.elem = elem;
this.element = $(elem);
this.value = "";
this.positions = ["top-left", "top", "top-right", "right", "bottom-right", "bottom", "bottom-left", "left"];
this.keypad = null;
this._setOptionsFromDOM();
this.keys = Utils.strToArray(this.options.keys, ",");
this.keys_to_work = this.keys;
this._create();
return this;
},
options: {
keySize: 32,
keys: "1, 2, 3, 4, 5, 6, 7, 8, 9, 0",
copyInlineStyles: false,
target: null,
length: 0,
shuffle: false,
shuffleCount: 3,
position: Metro.position.BOTTOM_LEFT, //top-left, top, top-right, right, bottom-right, bottom, bottom-left, left
dynamicPosition: false,
serviceButtons: true,
showValue: true,
open: false,
sizeAsKeys: false,
clsKeypad: "",
clsInput: "",
clsKeys: "",
clsKey: "",
clsServiceKey: "",
clsBackspace: "",
clsClear: "",
onChange: Metro.noop,
onClear: Metro.noop,
onBackspace: Metro.noop,
onShuffle: Metro.noop,
onKey: Metro.noop,
onKeypadCreate: 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._createKeypad();
if (this.options.shuffle === true) {
this.shuffle();
}
this._createKeys();
this._createEvents();
Utils.exec(this.options.onKeypadCreate, [this.element]);
},
_createKeypad: function(){
var element = this.element, o = this.options;
var prev = element.prev();
var parent = element.parent();
var keypad, keys;
if (parent.hasClass("input")) {
keypad = parent;
} else {
keypad = $("<div>").addClass("input").addClass(element[0].className);
}
keypad.addClass("keypad");
if (keypad.css("position") === "static" || keypad.css("position") === "") {
keypad.css({
position: "relative"
});
}
if (element.attr("type") === undefined) {
element.attr("type", "text");
}
if (prev.length === 0) {
parent.prepend(keypad);
} else {
keypad.insertAfter(prev);
}
element.attr("readonly", true);
element.appendTo(keypad);
keys = $("<div>").addClass("keys").addClass(o.clsKeys);
keys.appendTo(keypad);
this._setKeysPosition();
if (o.open === true) {
keys.addClass("open keep-open");
}
element[0].className = '';
if (o.copyInlineStyles === true) {
for (var i = 0, l = element[0].style.length; i < l; i++) {
keypad.css(element[0].style[i], element.css(element[0].style[i]));
}
}
element.addClass(o.clsInput);
keypad.addClass(o.clsKeypad);
element.on(Metro.events.blur, function(){keypad.removeClass("focused");});
element.on(Metro.events.focus, function(){keypad.addClass("focused");});
if (o.disabled === true || element.is(":disabled")) {
this.disable();
} else {
this.enable();
}
this.keypad = keypad;
},
_setKeysPosition: function(){
var element = this.element, o = this.options;
var keypad = element.parent();
var keys = keypad.find(".keys");
keys.removeClass(this.positions.join(" ")).addClass(o.position)
},
_createKeys: function(){
var element = this.element, o = this.options;
var keypad = element.parent();
var factor = Math.round(Math.sqrt(this.keys.length + 2));
var key_size = o.keySize;
var width = factor * key_size + factor * 4;
var key, keys = keypad.find(".keys");
keys.html("");
$.each(this.keys_to_work, function(){
key = $("<span>").addClass("key").addClass(o.clsKey).html(this);
key.data("key", this);
key.css({
width: o.keySize,
height: o.keySize,
lineHeight: o.keySize - 4 + "px"
}).appendTo(keys);
});
if (o.serviceButtons === true) {
var service_keys = ['←', '×'];
$.each(service_keys, function () {
key = $("<span>").addClass("key service-key").addClass(o.clsKey).addClass(o.clsServiceKey).html(this);
if (this === '←') {
key.addClass(o.clsBackspace);
}
if (this === '×') {
key.addClass(o.clsClear);
}
key.data("key", this);
key.css({
width: o.keySize,
height: o.keySize,
lineHeight: o.keySize - 4 + "px"
}).appendTo(keys);
});
}
keys.width(width);
if (o.sizeAsKeys === true && ['top-left', 'top', 'top-right', 'bottom-left', 'bottom', 'bottom-right'].indexOf(o.position) !== -1) {
keypad.outerWidth(keys.outerWidth());
}
},
_createEvents: function(){
var that = this, element = this.element, o = this.options;
var keypad = element.parent();
var keys = keypad.find(".keys");
keypad.on(Metro.events.click, ".keys", function(e){
e.preventDefault();
e.stopPropagation();
});
keypad.on(Metro.events.click, function(e){
if (o.open === true) {
return ;
}
if (keys.hasClass("open") === true) {
keys.removeClass("open");
} else {
keys.addClass("open");
}
e.preventDefault();
e.stopPropagation();
});
keypad.on(Metro.events.click, ".key", function(e){
var key = $(this);
if (key.data('key') !== '←' && key.data('key') !== '×') {
if (o.length > 0 && (String(that.value).length === o.length)) {
return false;
}
that.value = that.value + "" + key.data('key');
if (o.shuffle === true) {
that.shuffle();
that._createKeys();
}
if (o.dynamicPosition === true) {
o.position = that.positions[Utils.random(0, that.positions.length - 1)];
that._setKeysPosition();
}
Utils.exec(o.onKey, [key.data('key'), that.value, element]);
} else {
if (key.data('key') === '×') {
that.value = "";
Utils.exec(o.onClear, [element]);
}
if (key.data('key') === '←') {
that.value = (that.value.substring(0, that.value.length - 1));
Utils.exec(o.onBackspace, [that.value, element]);
}
}
if (o.showValue === true) {
if (element[0].tagName === "INPUT") {
element.val(that.value);
} else {
element.text(that.value);
}
}
element.trigger('change');
Utils.exec(o.onChange, [that.value, element]);
e.preventDefault();
e.stopPropagation();
});
if (o.target !== null) {
element.on(Metro.events.change, function(){
var t = $(o.target);
if (t.length === 0) {
return ;
}
if (t[0].tagName === "INPUT") {
t.val(that.value);
} else {
t.text(that.value);
}
});
}
},
shuffle: function(){
for (var i = 0; i < this.options.shuffleCount; i++) {
this.keys_to_work = this.keys_to_work.shuffle();
}
Utils.exec(this.options.onShuffle, [this.keys_to_work, this.keys, this.element]);
},
shuffleKeys: function(count){
if (count === undefined) {
count = this.options.shuffleCount;
}
for (var i = 0; i < count; i++) {
this.keys_to_work = this.keys_to_work.shuffle();
}
this._createKeys();
},
val: function(v){
if (v !== undefined) {
this.value = v;
this.element[0].tagName === "INPUT" ? this.element.val(v) : this.element.text(v);
} else {
return this.value;
}
},
open: function(){
var element = this.element;
var keypad = element.parent();
var keys = keypad.find(".keys");
keys.addClass("open");
},
close: function(){
var element = this.element;
var keypad = element.parent();
var keys = keypad.find(".keys");
keys.removeClass("open");
},
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();
}
},
setPosition: function(pos){
var new_position = pos !== undefined ? pos : this.element.attr("data-position");
if (this.positions.indexOf(new_position) === -1) {
return ;
}
this.options.position = new_position;
this._setKeysPosition();
},
changeAttribute: function(attributeName){
switch (attributeName) {
case 'disabled': this.toggleState(); break;
case 'data-position': this.setPosition(); break;
}
},
destroy: function(){
var element = this.element, keypad = this.keypad;
keypad.off(Metro.events.click, ".keys");
keypad.off(Metro.events.click);
keypad.off(Metro.events.click, ".key");
element.off(Metro.events.change);
element.insertBefore(keypad);
keypad.remove();
}
};
Metro.plugin('keypad', Keypad);
$(document).on(Metro.events.click, function(){
var keypads = $(".keypad .keys");
$.each(keypads, function(){
if (!$(this).hasClass("keep-open")) {
$(this).removeClass("open");
}
});
});