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
246 lines (196 loc) • 7.46 kB
JavaScript
var Spinner = {
init: function( options, elem ) {
this.options = $.extend( {}, this.options, options );
this.elem = elem;
this.element = $(elem);
this.repeat_timer = false;
this._setOptionsFromDOM();
this._create();
return this;
},
options: {
step: 1,
plusIcon: "<span class='default-icon-plus'></span>",
minusIcon: "<span class='default-icon-minus'></span>",
buttonsPosition: "default",
defaultValue: 0,
minValue: null,
maxValue: null,
fixed: 0,
repeatThreshold: 500,
hideCursor: false,
clsSpinner: "",
clsSpinnerInput: "",
clsSpinnerButton: "",
clsSpinnerButtonPlus: "",
clsSpinnerButtonMinus: "",
onBeforeChange: Metro.noop_true,
onChange: Metro.noop,
onPlusClick: Metro.noop,
onMinusClick: Metro.noop,
onArrowUp: Metro.noop,
onArrowDown: Metro.noop,
onButtonClick: Metro.noop,
onArrowClick: Metro.noop,
onSpinnerCreate: 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(){
var element = this.element, o = this.options;
this._createStructure();
this._createEvents();
Utils.exec(o.onCreate, [element]);
},
_createStructure: function(){
var element = this.element, o = this.options;
var spinner = $("<div>").addClass("spinner").addClass("buttons-"+o.buttonsPosition).addClass(element[0].className).addClass(o.clsSpinner);
var button_plus = $("<button>").attr("type", "button").addClass("button spinner-button spinner-button-plus").addClass(o.clsSpinnerButton + " " + o.clsSpinnerButtonPlus).html(o.plusIcon);
var button_minus = $("<button>").attr("type", "button").addClass("button spinner-button spinner-button-minus").addClass(o.clsSpinnerButton + " " + o.clsSpinnerButtonMinus).html(o.minusIcon);
var init_value = element.val().trim();
if (!Utils.isValue(init_value)) {
element.val(0);
}
element[0].className = '';
spinner.insertBefore(element);
element.appendTo(spinner).addClass(o.clsSpinnerInput);
element.addClass("original-input");
button_plus.appendTo(spinner);
button_minus.appendTo(spinner);
if (o.hideCursor === true) {
spinner.addClass("hide-cursor");
}
if (o.disabled === true || element.is(":disabled")) {
this.disable();
} else {
this.enable();
}
},
_createEvents: function(){
var that = this, element = this.element, o = this.options;
var spinner = element.closest(".spinner");
var spinner_buttons = spinner.find(".spinner-button");
var spinnerButtonClick = function(plus, threshold){
var curr = element.val();
var val = Number(element.val());
var step = Number(o.step);
if (plus) {
val += step;
} else {
val -= step;
}
that._setValue(val.toFixed(o.fixed), true);
Utils.exec(plus ? o.onPlusClick : o.onMinusClick, [curr, val, element.val()], element[0]);
Utils.exec(plus ? o.onArrowUp : o.onArrowDown, [curr, val, element.val()], element[0]);
Utils.exec(o.onButtonClick, [curr, val, element.val(), plus ? 'plus' : 'minus'], element[0]);
Utils.exec(o.onArrowClick, [curr, val, element.val(), plus ? 'plus' : 'minus'], element[0]);
setTimeout(function(){
if (that.repeat_timer) {
spinnerButtonClick(plus, 100);
}
}, threshold);
};
spinner.on(Metro.events.click, function(e){
$(".focused").removeClass("focused");
spinner.addClass("focused");
e.preventDefault();
e.stopPropagation();
});
spinner_buttons.on(Metro.events.start, function(e){
e.preventDefault();
that.repeat_timer = true;
spinnerButtonClick($(this).hasClass("spinner-button-plus"), o.repeatThreshold);
});
spinner_buttons.on(Metro.events.stop, function(){
that.repeat_timer = false;
});
element.on(Metro.events.keydown, function(e){
if (e.keyCode === Metro.keyCode.UP_ARROW || e.keyCode === Metro.keyCode.DOWN_ARROW) {
that.repeat_timer = true;
spinnerButtonClick(e.keyCode === Metro.keyCode.UP_ARROW, o.repeatThreshold);
}
});
spinner.on(Metro.events.keyup, function(){
that.repeat_timer = false;
});
},
_setValue: function(val, trigger_change){
var element = this.element, o = this.options;
if (Utils.exec(o.onBeforeChange, [val], element[0]) !== true) {
return ;
}
if (Utils.isValue(o.maxValue) && val > Number(o.maxValue)) {
val = Number(o.maxValue);
}
if (Utils.isValue(o.minValue) && val < Number(o.minValue)) {
val = Number(o.minValue);
}
element.val(val);
Utils.exec(o.onChange, [val], element[0]);
if (trigger_change === true) {
element.trigger("change");
}
},
val: function(val){
var that = this, element = this.element, o = this.options;
if (!Utils.isValue(val)) {
return element.val();
}
that._setValue(val.toFixed(o.fixed), true);
},
toDefault: function(){
var element = this.element, o = this.options;
var val = Utils.isValue(o.defaultValue) ? Number(o.defaultValue) : 0;
this._setValue(val.toFixed(o.fixed), true);
Utils.exec(o.onChange, [val], 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();
}
},
changeAttribute: function(attributeName){
var that = this, element = this.element;
var changeValue = function(){
var val = element.attr('value').trim();
if (Utils.isValue(val)) {
that._setValue(Number(val), false);
}
};
switch (attributeName) {
case 'disabled': this.toggleState(); break;
case 'value': changeValue(); break;
}
},
destroy: function(){
var element = this.element;
var spinner = element.closest(".spinner");
spinner.off(Metro.events.click, ".spinner-button");
element.insertBefore(spinner);
spinner.remove();
}
};
Metro.plugin('spinner', Spinner);
$(document).on(Metro.events.click, function(){
$(".spinner").removeClass("focused");
});