/**
 * spinner - jQuery jwwUI Copyright (c) 2013-2015 www.jeeww.com. All rights reserved. 
 * Licensed under the GPL or commercial licenses 
 */
(function($) {
    function create(target, definationsTemp) {
        var spinnerObj = $(
                "<div class=\"spinner\">" + "<div class=\"spinner-arrow\">" + "<div class=\"spinner-arrow-up\"></div>"
                        + "<div class=\"spinner-arrow-down\"></div>" + "</div>" + "</div>").insertAfter(target);
        if (definationsTemp.cusCls) {
            $(target).addClass(definationsTemp.cusCls)
        }
        $(target).addClass("spinner-text spinner-f").prependTo(spinnerObj);
        return spinnerObj;
    }
    ;
    function resizeSpinner(target, width) {
        var definations = $.data(target, "spinner").definations;
        var spinner = $.data(target, "spinner").spinner;
        if (width) {
            definations.width = width;
        }
        var spinnerArrow = spinner.find(".spinner-arrow");
        spinner._outerWidth(definations.width)._outerHeight(definations.height);
        $(target)._outerWidth(spinner.width() - spinnerArrow.outerWidth());
        $(target).css({ height : spinner.height() + "px", lineHeight : spinner.height() + "px" });
        var spinnerTextObj = spinner.find("input.spinner-text");
        spinnerTextObj._outerWidth(spinner.width() - spinnerArrow.outerWidth());
    }
    ;
    function bindSpinnerInfo(_c) {
        var definations = $.data(_c, "spinner").definations;
        var spinner = $.data(_c, "spinner").spinner;
        spinner.find(".spinner-arrow-up,.spinner-arrow-down").unbind(".spinner");
        if (!definations.disabled) {
            spinner.find(".spinner-arrow-up").bind("mouseenter.spinner", function() {
                $(this).addClass("spinner-arrow-hover");
            }).bind("mouseleave.spinner", function() {
                $(this).removeClass("spinner-arrow-hover");
            }).bind("click.spinner", function() {
                definations.spin.call(_c, false);
                definations.onSpinUp.call(_c);
                $(_c).inputbox("validate");
            });
            spinner.find(".spinner-arrow-down").bind("mouseenter.spinner", function() {
                $(this).addClass("spinner-arrow-hover");
            }).bind("mouseleave.spinner", function() {
                $(this).removeClass("spinner-arrow-hover");
            }).bind("click.spinner", function() {
                definations.spin.call(_c, true);
                definations.onSpinDown.call(_c);
                $(_c).inputbox("validate");
            });
        }
    }
    ;
    function disableOrEnable(target, flag) {
        var definations = $.data(target, "spinner").definations;
        if (flag) {
            definations.disabled = true;
            $(target).attr("disabled", true);
        } else {
            definations.disabled = false;
            $(target).removeAttr("disabled");
        }
    }
    ;
    $.fn.spinner = function(definations, param) {
        if (typeof definations == "string") {
            var fun = $.fn.spinner.methods[definations];
            if (fun) {
                return fun(this, param);
            } else {
                return this.inputbox(definations, param);
            }
        }
        definations = definations || {};
        return this.each(function() {
            var spinner = $.data(this, "spinner");
            if (spinner) {
                $.extend(spinner.definations, definations);
            } else {
                var definationsTemp = $.extend({}, $.fn.spinner.defaults, $.fn.spinner.parseDefinations(this), definations);
                spinner = $.data(this, "spinner", { definations : definationsTemp, spinner : create(this, definationsTemp) });
                $(this).removeAttr("disabled");
            }
            spinner.definations.originalValue = spinner.definations.value;
            $(this).val(spinner.definations.value);
            $(this).attr("readonly", !spinner.definations.editable);
            disableOrEnable(this, spinner.definations.disabled);
            resizeSpinner(this);
            $(this).inputbox(spinner.definations);
            bindSpinnerInfo(this);
        });
    };
    $.fn.spinner.methods = { definations : function(jq) {
        var definations = $.data(jq[0], "spinner").definations;
        return $.extend(definations, { value : jq.val() });
    }, destroy : function(jq) {
        return jq.each(function() {
            var spinner = $.data(this, "spinner").spinner;
            $(this).inputbox("destroy");
            spinner.remove();
        });
    }, resize : function(jq, width) {
        return jq.each(function() {
            resizeSpinner(this, width);
        });
    }, enable : function(jq) {
        return jq.each(function() {
            disableOrEnable(this, false);
            bindSpinnerInfo(this);
        });
    }, disable : function(jq) {
        return jq.each(function() {
            disableOrEnable(this, true);
            bindSpinnerInfo(this);
        });
    }, getValue : function(jq) {
        return jq.val();
    }, setValue : function(jq, value) {
        return jq.each(function() {
            var definations = $.data(this, "spinner").definations;
            definations.value = value;
            $(this).val(value);
        });
    }, clear : function(jq) {
        return jq.each(function() {
            var definations = $.data(this, "spinner").definations;
            definations.value = "";
            $(this).val("");
        });
    }, reset : function(jq) {
        return jq.each(function() {
            var definations = $(this).spinner("definations");
            $(this).spinner("setValue", definations.originalValue);
        });
    } };
    $.fn.spinner.parseDefinations = function(target) {
        var t = $(target);
        return $.extend({}, $.fn.inputbox.parseDefinations(target), $.parser.parseDefinations(target, [ "width", "height", "min",
                "max", { increment : "number", editable : "boolean" } ]), { value : (t.val() || undefined),
            disabled : (t.attr("disabled") ? true : undefined) });
    };
    $.fn.spinner.defaults = $.extend({}, $.fn.inputbox.defaults, { width : "auto", height : 22, value : "", min : null,
        max : null, increment : 1, editable : true, disabled : false, spin : function(num) {
        }, onSpinUp : function() {
        }, onSpinDown : function() {
        } });
})(jQuery);
