Subversion Repositories Integrator Subversion

Rev

Blame | Last modification | View Log | Download | RSS feed

/*
 * Fuel UX Spinner
 * https://github.com/ExactTarget/fuelux
 *
 * Copyright (c) 2012 ExactTarget
 * Licensed under the MIT license.
 */


!function ($) {
        // SPINNER CONSTRUCTOR AND PROTOTYPE

        var Spinner = function (element, options) {
                this.$element = $(element);
                this.options = $.extend({}, $.fn.spinner.defaults, options);
                this.$input = this.$element.find('.spinner-input');
                this.$element.on('keyup', this.$input, $.proxy(this.change, this));

                if (this.options.hold) {
                        this.$element.on('mousedown', '.spinner-up', $.proxy(function() { this.startSpin(true); } , this));
                        this.$element.on('mouseup', '.spinner-up, .spinner-down', $.proxy(this.stopSpin, this));
                        this.$element.on('mouseout', '.spinner-up, .spinner-down', $.proxy(this.stopSpin, this));
                        this.$element.on('mousedown', '.spinner-down', $.proxy(function() {this.startSpin(false);} , this));
                } else {
                        this.$element.on('click', '.spinner-up', $.proxy(function() { this.step(true); } , this));
                        this.$element.on('click', '.spinner-down', $.proxy(function() { this.step(false); }, this));
                }

                this.switches = {
                        count: 1,
                        enabled: true
                };

                if (this.options.speed === 'medium') {
                        this.switches.speed = 300;
                } else if (this.options.speed === 'fast') {
                        this.switches.speed = 100;
                } else {
                        this.switches.speed = 500;
                }

                this.lastValue = null;

                this.render();

                if (this.options.disabled) {
                        this.disable();
                }
        };

        Spinner.prototype = {
                constructor: Spinner,

                render: function () {
                        var inputValue = this.$input.val();

                        if (inputValue) {
                                this.value(inputValue);
                        } else {
                                this.$input.val(this.options.value);
                        }

                        this.$input.attr('maxlength', (this.options.max + '').split('').length);
                },

                change: function () {
                        var newVal = this.$input.val();

                        if(newVal/1){
                                this.options.value = newVal/1;
                        }else{
                                newVal = newVal.replace(/[^0-9]/g,'');
                                this.$input.val(newVal);
                                this.options.value = newVal/1;
                        }

                        this.triggerChangedEvent();
                },

                stopSpin: function () {
                        clearTimeout(this.switches.timeout);
                        this.switches.count = 1;
                        this.triggerChangedEvent();
                },

                triggerChangedEvent: function () {
                        var currentValue = this.value();
                        if (currentValue === this.lastValue) return;

                        this.lastValue = currentValue;

                        // Primary changed event
                        this.$element.trigger('changed', currentValue);

                        // Undocumented, kept for backward compatibility
                        this.$element.trigger('change');
                },

                startSpin: function (type) {

                        if (!this.options.disabled) {
                                var divisor = this.switches.count;

                                if (divisor === 1) {
                                        this.step(type);
                                        divisor = 1;
                                } else if (divisor < 3){
                                        divisor = 1.5;
                                } else if (divisor < 8){
                                        divisor = 2.5;
                                } else {
                                        divisor = 4;
                                }

                                this.switches.timeout = setTimeout($.proxy(function() {this.iterator(type);} ,this),this.switches.speed/divisor);
                                this.switches.count++;
                        }
                },

                iterator: function (type) {
                        this.step(type);
                        this.startSpin(type);
                },

                step: function (dir) {
                        var curValue = this.options.value;
                        var limValue = dir ? this.options.max : this.options.min;

                        if ((dir ? curValue < limValue : curValue > limValue)) {
                                var newVal = curValue + (dir ? 1 : -1) * this.options.step;

                                if (dir ? newVal > limValue : newVal < limValue) {
                                        this.value(limValue);
                                } else {
                                        this.value(newVal);
                                }
                        } else if (this.options.cycle) {
                                var cycleVal = dir ? this.options.min : this.options.max;
                                this.value(cycleVal);
                        }
                },

                value: function (value) {
                        if (!isNaN(parseFloat(value)) && isFinite(value)) {
                                value = parseFloat(value);
                                this.options.value = value;
                                this.$input.val(value);
                                return this;
                        } else {
                                return this.options.value;
                        }
                },

                disable: function () {
                        this.options.disabled = true;
                        this.$input.attr('disabled','');
                        this.$element.find('button').addClass('disabled');
                },

                enable: function () {
                        this.options.disabled = false;
                        this.$input.removeAttr("disabled");
                        this.$element.find('button').removeClass('disabled');
                }
        };


        // SPINNER PLUGIN DEFINITION

        $.fn.spinner = function (option,value) {
                var methodReturn;

                var $set = this.each(function () {
                        var $this = $(this);
                        var data = $this.data('spinner');
                        var options = typeof option === 'object' && option;

                        if (!data) $this.data('spinner', (data = new Spinner(this, options)));
                        if (typeof option === 'string') methodReturn = data[option](value);
                });

                return (methodReturn === undefined) ? $set : methodReturn;
        };

        $.fn.spinner.defaults = {
                value: 1,
                min: 1,
                max: 999,
                step: 1,
                hold: true,
                speed: 'medium',
                disabled: false
        };

        $.fn.spinner.Constructor = Spinner;


        // SPINNER DATA-API

        $(function () {
                $('body').on('mousedown.spinner.data-api', '.spinner', function () {
                        var $this = $(this);
                        if ($this.data('spinner')) return;
                        $this.spinner($this.data());
                });
        });
       
}(window.jQuery);