      1 /*
      2  * JBoss, Home of Professional Open Source
      3  * Copyright ${year}, Red Hat, Inc. and individual contributors
      4  * by the @authors tag. See the copyright.txt in the distribution for a
      5  * full listing of individual contributors.
      6  *
      7  * This is free software; you can redistribute it and/or modify it
      8  * under the terms of the GNU Lesser General Public License as
      9  * published by the Free Software Foundation; either version 2.1 of
     10  * the License, or (at your option) any later version.
     11  *
     12  * This software is distributed in the hope that it will be useful,
     13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
     15  * Lesser General Public License for more details.
     16  *
     17  * You should have received a copy of the GNU Lesser General Public
     18  * License along with this software; if not, write to the Free
     19  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
     20  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
     21  */
     22 (function($, rf) {
     23     rf.ui = rf.ui || {};
     24
     25     rf.ui.InputNumberSpinner = rf.BaseComponent.extendClass({
     26
     27             name: "InputNumberSpinner",
     28
     29             cycled: true,
     30             delay: 200,
     31             maxValue: 100,
     32             minValue: 0,
     33             step: 1,
     34
     35             init: function (id, options) {
     36                 $super.constructor.call(this, id);
     37                 $.extend(this, options);
     38                 this.element = $(this.attachToDom());
     39                 this.input = this.element.children(".rf-insp-inp");
     40
     41                 var value = Number(this.input.val());
     42                 if (isNaN(value)) {
     43                     value = this.minValue;
     44                 }
     45                 this.__setValue(value, null, true);
     46
     47                 if (!this.input.attr("disabled")) {
     48                     var buttonsArea = this.element.children(".rf-insp-btns");
     49                     this.decreaseButton = buttonsArea.children(".rf-insp-dec");
     50                     this.increaseButton = buttonsArea.children(".rf-insp-inc");
     51
     52                     var proxy = $.proxy(this.__inputHandler, this)
     53                     this.input.change(proxy);
     54                     this.input.submit(proxy);
     55                     this.input.submit(proxy);
     56                     this.input.mousewheel($.proxy(this.__mousewheelHandler, this));
     57                     this.input.keydown($.proxy(this.__keydownHandler, this));
     58                     this.decreaseButton.mousedown($.proxy(this.__decreaseHandler, this));
     59                     this.increaseButton.mousedown($.proxy(this.__increaseHandler, this));
     60                 }
     61             },
     62
     63             decrease: function (event) {
     64                 var value = this.value - this.step;
     65                 value = this.roundFloat(value);
     66                 if (value < this.minValue && this.cycled) {
     67                     value = this.maxValue;
     68                 }
     69                 this.__setValue(value, event);
     70             },
     71
     72             increase: function (event) {
     73                 var value = this.value + this.step;
     74                 value = this.roundFloat(value);
     75
     76                 if (value > this.maxValue && this.cycled) {
     77                     value = this.minValue;
     78                 }
     79                 this.__setValue(value, event);
     80             },
     81
     82             getValue: function () {
     83                 return this.value;
     84             },
     85
     86             setValue: function (value, event) {
     87                 if (!this.input.attr("disabled")) {
     88                     this.__setValue(value);
     89                 }
     90             },
     91
     92             roundFloat: function(x){
     93                 var str = this.step.toString();
     94                 var power = 0;
     95                 if (!/\./.test(str)) {
     96                     if (this.step >= 1) {
     97                         return x;
     98                     }
     99                     if (/e/.test(str)) {
    100                         power = str.split("-")[1];
    101                     }
    102                 } else {
    103                     power = str.length - str.indexOf(".") - 1;
    104                 }
    105                 var ret = x.toFixed(power);
    106                 return parseFloat(ret);
    107             },
    108
    109             destroy: function (event) {
    110                 if (this.intervalId) {
    111                     window.clearInterval(this.intervalId);
    112                     this.decreaseButton.css("backgroundPosition", " 50% 40%").unbind("mouseout", this.destroy)
    113                         .unbind("mouseup", this.destroy);
    114                     this.increaseButton.css("backgroundPosition", " 50% 40%").unbind("mouseout", this.destroy)
    115                         .unbind("mouseup", this.destroy);
    116                     this.intervalId = null;
    117                 }
    118                 $super.destroy.call(this);
    119             },
    120
    121             __setValue: function (value, event, skipOnchange) {
    122                 if (!isNaN(value)) {
    123                     if (value > this.maxValue) {
    124                         value = this.maxValue;
    125                         this.input.val(value);
    126                     } else if (value < this.minValue) {
    127                         value = this.minValue;
    128                         this.input.val(value);
    129                     }
    130                     if (value != this.value) {
    131                         this.input.val(value);
    132                         this.value = value;
    133                         if (this.onchange && !skipOnchange) {
    134                             this.onchange.call(this.element[0], event);
    135                         }
    136                     }
    137                 }
    138             },
    139
    140             __inputHandler: function (event) {
    141                 var value = Number(this.input.val());
    142                 if (isNaN(value)) {
    143                     this.input.val(this.value);
    144                 } else {
    145                     this.__setValue(value, event);
    146                 }
    147             },
    148
    149             __mousewheelHandler: function (event, delta, deltaX, deltaY) {
    150                 delta = deltaX || deltaY;
    151                 if (delta > 0) {
    152                     this.increase(event);
    153                 } else if (delta < 0) {
    154                     this.decrease(event);
    155                 }
    156                 return false;
    157             },
    158
    159             __keydownHandler: function (event) {
    160                 if (event.keyCode == 40) { //DOWN
    161                     this.decrease(event);
    162                     event.preventDefault();
    163                 } else if (event.keyCode == 38) { //UP
    164                     this.increase(event);
    165                     event.preventDefault();
    166                 }
    167             },
    168
    169             __decreaseHandler: function (event) {
    170                 var component = this;
    171                 component.decrease(event);
    172                 this.intervalId = window.setInterval(function() {
    173                     component.decrease(event);
    174                 }, this.delay);
    175                 var proxy = $.proxy(this.destroy, this);
    176                 this.decreaseButton.bind("mouseup", proxy).bind("mouseout", proxy)
    177                     .css("backgroundPosition", "60% 60%");
    178                 event.preventDefault();
    179             },
    180
    181             __increaseHandler: function (event) {
    182                 var component = this;
    183                 component.increase(event);
    184                 this.intervalId = window.setInterval(function() {
    185                     component.increase(event);
    186                 }, this.delay);
    187                 var proxy = $.proxy(this.destroy, this);
    188                 this.increaseButton.bind("mouseup", proxy).bind("mouseout", proxy)
    189                     .css("backgroundPosition", "60% 60%");
    190                 event.preventDefault();
    191             }
    192         });
    193
    194     // define super class link
    195     var $super = rf.ui.InputNumberSpinner.$super;
    196 }(RichFaces.jQuery, window.RichFaces));