      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.InputNumberSlider = rf.BaseComponent.extendClass({
     26
     27             name: "InputNumberSlider",
     28
     29             delay: 200,
     30             maxValue: 100,
     31             minValue: 0,
     32             step: 1,
     33             tabIndex: 0,
     34
     35             decreaseSelectedClass: "rf-insl-dec-sel",
     36             handleSelectedClass: "rf-insl-hnd-sel",
     37             increaseSelectedClass: "rf-insl-inc-sel",
     38
     39             init: function (id, options, selectedClasses) {
     40                 $superInputNumberSlider.constructor.call(this, id);
     41                 $.extend(this, options);
     42                 this.range = this.maxValue - this.minValue;
     43                 this.id = id;
     44                 this.element = $(this.attachToDom());
     45                 this.input = this.element.children(".rf-insl-inp-cntr").children(".rf-insl-inp");
     46                 this.track = this.element.children(".rf-insl-trc-cntr").children(".rf-insl-trc");
     47                 this.handleContainer = this.track.children("span");
     48                 this.handle = this.handleContainer.children(".rf-insl-hnd, .rf-insl-hnd-dis");
     49                 this.tooltip = this.element.children(".rf-insl-tt");
     50
     51                 var value = Number(this.input.val());
     52                 if (isNaN(value)) {
     53                     value = this.minValue;
     54                 }
     55                 this.handleContainer.css("display", "block");
     56                 this.track.css("padding-right", this.handle.width() + "px");
     57                 this.__setValue(value, null, true);
     58
     59                 if (!this.disabled) {
     60                     this.decreaseButton = this.element.children(".rf-insl-dec");
     61                     this.increaseButton = this.element.children(".rf-insl-inc");
     62
     63                     this.track[0].tabIndex = this.tabIndex;
     64
     65                     for (var i in selectedClasses) {
     66                         this[i] += " " + selectedClasses[i];
     67                     }
     68                     var proxy = $.proxy(this.__inputHandler, this);
     69                     this.input.change(proxy);
     70                     this.input.submit(proxy);
     71                     this.element.mousewheel($.proxy(this.__mousewheelHandler, this));
     72                     this.track.keydown($.proxy(this.__keydownHandler, this));
     73                     this.decreaseButton.mousedown($.proxy(this.__decreaseHandler, this));
     74                     this.increaseButton.mousedown($.proxy(this.__increaseHandler, this));
     75                     this.track.mousedown($.proxy(this.__mousedownHandler, this));
     76                 }
     77             },
     78
     79             decrease: function (event) {
     80                 var value = this.value - this.step;
     81                 value = this.roundFloat(value);
     82                 this.setValue(value, event);
     83             },
     84
     85             increase: function (event) {
     86                 var value = this.value + this.step;
     87                 value = this.roundFloat(value);
     88                 this.setValue(value, event);
     89             },
     90
     91             getValue: function () {
     92                 return this.value;
     93             },
     94
     95             setValue: function (value, event) {
     96                 if (!this.disabled) {
     97                     this.__setValue(value, event);
     98                 }
     99             },
    100
    101             roundFloat: function(x){
    102                 var str = this.step.toString();
    103                 var power = 0;
    104                 if (!/\./.test(str)) {
    105                     if (this.step >= 1) {
    106                         return x;
    107                     }
    108                     if (/e/.test(str)) {
    109                         power = str.split("-")[1];
    110                     }
    111                 } else {
    112                     power = str.length - str.indexOf(".") - 1;
    113                 }
    114                 var ret = x.toFixed(power);
    115                 return parseFloat(ret);
    116             },
    117
    118             __setValue: function (value, event, skipOnchange) {
    119                 if (!isNaN(value)) {
    120                     var changed = false;
    121                     if (this.input.val() == "") {
    122                         // value already changed from "" to 0, compare to real value to track changes
    123                         changed = true;
    124                     }
    125
    126                     if (value > this.maxValue) {
    127                         value = this.maxValue;
    128                         this.input.val(value);
    129                         changed = true;
    130                     } else if (value < this.minValue) {
    131                         value = this.minValue;
    132                         this.input.val(value);
    133                         changed = true;
    134                     }
    135                     if (value != this.value || changed) {
    136                         this.input.val(value);
    137                         var left = 100 * (value - this.minValue) / this.range;
    138                         if(this.handleType=='bar') {
    139                             this.handleContainer.css("width", left + "%");
    140                         } else {
    141                             this.handleContainer.css("padding-left", left + "%");
    142                         }
    143                         this.tooltip.text(value);
    144                         this.tooltip.setPosition(this.handle, {from: 'LT', offset: [0, 5]}); //TODO Seems offset doesn't work now.
    145                         this.value = value;
    146                         if (this.onchange && !skipOnchange) {
    147                             this.onchange.call(this.element[0], event);
    148                         }
    149                     }
    150                 }
    151             },
    152
    153             __inputHandler: function (event) {
    154                 var value = Number(this.input.val());
    155                 if (isNaN(value)) {
    156                     this.input.val(this.value);
    157                 } else {
    158                     this.__setValue(value, event);
    159                 }
    160             },
    161
    162             __mousewheelHandler: function (event, delta, deltaX, deltaY) {
    163                 delta = deltaX || deltaY;
    164                 if (delta > 0) {
    165                     this.increase(event);
    166                 } else if (delta < 0) {
    167                     this.decrease(event);
    168                 }
    169                 return false;
    170             },
    171
    172             __keydownHandler: function (event) {
    173                 if (event.keyCode == 37) { //LEFT
    174                     var value = Number(this.input.val()) - this.step;
    175                     value = this.roundFloat(value);
    176                     this.__setValue(value, event);
    177                     event.preventDefault();
    178                 } else if (event.keyCode == 39) { //RIGHT
    179                     var value = Number(this.input.val()) + this.step;
    180                     value = this.roundFloat(value);
    181                     this.__setValue(value, event);
    182                     event.preventDefault();
    183                 }
    184             },
    185
    186             __decreaseHandler: function (event) {
    187                 var component = this;
    188                 component.decrease(event);
    189                 this.intervalId = window.setInterval(function() {
    190                     component.decrease(event);
    191                 }, this.delay);
    192                 $(document).one("mouseup", true, $.proxy(this.__clearInterval, this));
    193                 this.decreaseButton.addClass(this.decreaseSelectedClass);
    194                 event.preventDefault();
    195             },
    196
    197             __increaseHandler: function (event) {
    198                 var component = this;
    199                 component.increase(event);
    200                 this.intervalId = window.setInterval(function() {
    201                     component.increase(event);
    202                 }, this.delay);
    203                 $(document).one("mouseup", $.proxy(this.__clearInterval, this));
    204                 this.increaseButton.addClass(this.increaseSelectedClass);
    205                 event.preventDefault();
    206             },
    207
    208             __clearInterval: function (event) {
    209                 window.clearInterval(this.intervalId);
    210                 if (event.data) { // decreaseButton
    211                     this.decreaseButton.removeClass(this.decreaseSelectedClass);
    212                 } else {
    213                     this.increaseButton.removeClass(this.increaseSelectedClass);
    214                 }
    215             },
    216
    217             __mousedownHandler: function (event) {
    218                 this.__mousemoveHandler(event);
    219                 this.track.focus();
    220                 var jQueryDocument = $(document);
    221                 jQueryDocument.mousemove($.proxy(this.__mousemoveHandler, this));
    222                 jQueryDocument.one("mouseup", $.proxy(this.__mouseupHandler, this));
    223                 this.handle.addClass(this.handleSelectedClass);
    224                 this.tooltip.show();
    225             },
    226
    227             __mousemoveHandler: function (event) {
    228                 var value = this.range * (event.pageX - this.track.offset().left - this.handle.width() / 2) / (this.track.width()
    229                     - this.handle.width()) + this.minValue;
    230                 value = Math.round(value / this.step) * this.step;
    231                 value = this.roundFloat(value);
    232                 this.__setValue(value, event);
    233                 event.preventDefault();
    234             },
    235
    236             __mouseupHandler: function () {
    237                 this.handle.removeClass(this.handleSelectedClass);
    238                 this.tooltip.hide();
    239                 $(document).unbind("mousemove", this.__mousemoveHandler);
    240             },
    241
    242             destroy: function (event) {
    243                 $(document).unbind("mousemove", this.__mousemoveHandler);
    244                 $superInputNumberSlider.destroy.call(this);
    245             }
    246         });
    247     $superInputNumberSlider = rf.ui.InputNumberSlider.$super;
    248 }(RichFaces.jQuery, window.RichFaces));
    249