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));