// As usual, we keep the generic functions out of the namespace function addEvent(obj, evType, fn, useCapture){ if (obj.addEventListener){ obj.addEventListener(evType, fn, useCapture); return true; } else if (obj.attachEvent){ var r = obj.attachEvent("on"+evType, fn); return r; } return false; } function removeEvent(obj, evType, fn, useCapture){ if (obj.removeEventListener){ obj.removeEventListener(evType, fn, useCapture); return true; } else if (obj.detachEvent){ var r = obj.detachEvent("on"+evType, fn); return r; } return false; } if(!String.prototype.trim) String.prototype.trim = function() { return this.replace(/^\s*/,'').replace(/\s*$/, ''); }; var incrementalInputController; // Encapsulate the Timer and incrementalInput objects (function() { // WEBFX Timer : http://www.webfx.com/ function Timer(nPauseTime) { this._pauseTime = typeof nPauseTime == "undefined" ? 1000 : nPauseTime; this._timer = null; this._isStarted = false; } Timer.prototype.start = function () { if (this.isStarted()) this.stop(); var oThis = this; this._timer = window.setTimeout(function () { if (typeof oThis.ontimer == "function") oThis.ontimer(); }, this._pauseTime); this._isStarted = false; }; Timer.prototype.stop = function () { if (this._timer != null) window.clearTimeout(this._timer); this._isStarted = false; }; Timer.prototype.isStarted = function () { return this._isStarted; }; Timer.prototype.getPauseTime = function () { return this._pauseTime; }; Timer.prototype.setPauseTime = function (nPauseTime) { this._pauseTime = nPauseTime; }; function incrementalInput(inp, range, increment, classInc, classDec) { if(!inp || !range) return; this._inp = inp; this._buttonInc; this._buttonDec; this._value; this._classInc = classInc; this._classDec = classDec; this._minv = Number(range[0]); this._maxv = Number(range[1]); this._incBase = Number(increment) || 1; this._precision = 0; if(increment.indexOf('.') != -1) { this._precision = increment.substr(increment.indexOf('.')+1, increment.length); this._precision = this._precision.length; } this._increment; this._timerInc = 1000; this._timer = new Timer(1000); this._stop = false; this._key = false; this._events = { dec: function(e) { self._increment = -self._incBase; self.updateValue(); return false; }, inc: function(e) { self._increment = self._incBase; self.updateValue(); return false; }, keydec: function(e) { var kc; if (!e) var e = window.event; if (e.keyCode) kc = e.keyCode; else if (e.charCode) kc = e.charCode; if ( kc != 13 || self._key ) return true; self._key = true; self._increment = -self._incBase; self._timerInc = 1000; self.updateValue(); return false; }, keyinc: function(e) { var kc; if (!e) var e = window.event; if (e.keyCode) kc = e.keyCode; else if (e.charCode) kc = e.charCode; if ( kc != 13 || self._key ) return true; self._key = true; self._increment = self._incBase; self._timerInc = 1000; self.updateValue(); return false; }, clearTimer: function(e) { self._key = false; self._events.stopTimer(); }, stopTimer: function(e) { self._timer.stop(); self._timerInc = 1000; self._timer.setPauseTime(self._timerInc); }, onchange: function(e){ var value = Number(parseFloat(self._inp.value).toFixed(self._precision)); if( Number(value % self._incBase).toFixed(self._precision) != self._incBase ) { value -= Number(parseFloat(value % self._incBase)).toFixed(self._precision); }; if(value < self._minv) value = self._minv; else if(value > self._maxv) value = self._maxv; self._inp.value = parseFloat(value).toFixed(self._precision); } }; this.updateValue = function() { if(self._inp.disabled) { stopTimer(); return; } var value = Number(parseFloat(self._inp.value).toFixed(self._precision)); var stop = self._timerInc == 0 ? true : false; if( Math.abs(Number(value % self._incBase).toFixed(self._precision)) != self._incBase ) { value -= Number(parseFloat(value % self._incBase)).toFixed(self._precision); } value += Number(parseFloat(self._increment).toFixed(self._precision)); if(value < self._minv) { value = self._minv; stop = true; } else if(value > self._maxv) { value = self._maxv; stop = true; } self._inp.value = parseFloat(value).toFixed(self._precision); if(self._timerInc > 50) { self._timerInc = 50 + Math.round(((self._timerInc - 50) / 1.8)); } self._timer.setPauseTime(self._timerInc); if(!stop) self._timer.start(); }; this.construct = function() { var h = self._inp.offsetHeight; self._inp.onchange = self._events.onchange; self._buttonInc = document.createElement('button'); self._buttonDec = document.createElement('button'); if(self._classDec) self._buttonDec.className = self._classDec; if(self._classInc) self._buttonInc.className = self._classInc; self._buttonDec.setAttribute('type','button'); self._buttonInc.setAttribute('type','button'); self._buttonDec.appendChild(document.createTextNode('-')); self._buttonInc.appendChild(document.createTextNode('+')); self._buttonDec.onmousedown = self._events.dec; self._buttonInc.onmousedown = self._events.inc; addEvent(self._buttonDec, "keypress", self._events.keydec, true); addEvent(self._buttonDec, "keyup", self._events.clearTimer, true); addEvent(self._buttonInc, "keypress", self._events.keyinc, true); addEvent(self._buttonInc, "keyup", self._events.clearTimer, true); self._buttonInc.onmouseout = self._events.stopTimer; self._buttonDec.onmouseout = self._events.stopTimer; addEvent(document, 'mouseup', self._events.stopTimer, false); if(self._inp.nextSibling) { self._inp.parentNode.insertBefore( self._buttonDec, self._inp.nextSibling ); self._inp.parentNode.insertBefore( self._buttonInc, self._inp.nextSibling ); } else { self._inp.parentNode.appendChild( self._buttonInc ); self._inp.parentNode.appendChild( self._buttonDec ); }; }; var self = this; self._timer.ontimer = function() { self.updateValue(); }; self.construct(); } incremetalInputController = { inputCollection: [], constructor: function() { if(!document.getElementById || !document.createElement) return; // TODO : cut the regExps down to readable levels - they are hideous at present... var regExp_1 = /fd_incremental_inp_range_([-]{0,1}[0-9]+(f[0-9]+){0,1}){1}_([-]{0,1}[0-9]+(f[0-9]+){0,1}){1}/ig; var regExp_2 = /fd_increment_([0-9]+(f[0-9]+){0,1}){1}/ig; var regExp_3 = /fd_classname_inc_([\-_0-9a-zA-Z]+){1}/ig; var regExp_4 = /fd_classname_dec_([\-_0-9a-zA-Z]+){1}/ig; var inputCollection = document.getElementsByTagName('input'); var obj, range, classname, classes, classInc, classDec, increment; for(var i = 0, inp; inp = inputCollection[i]; i++) { if(inp.type == 'text' && inp.className && inp.className.search(regExp_1) != -1) { classes = inp.className.split(' '); increment = 1; range = [0,0]; classInc = ""; classDec = ""; for(var z = 0, classname; classname = classes[z]; z++) { if(classname.search(regExp_1) != -1) { range = classname.trim(); range = range.replace(/fd_incremental_inp_range_/ig, ''); range = range.replace(/f/g,'.'); range = range.split('_'); } else if(classname.search(regExp_2) != -1) { increment = classname.trim(); increment = increment.replace(/fd_increment_/ig, ''); increment = increment.replace('f','.'); } else if(classname.search(regExp_3) != -1) { classInc = classname.trim(); classInc = classInc.replace(/fd_classname_inc_/ig, ''); } else if(classname.search(regExp_4) != -1) { classDec = classname.trim(); classDec = classDec.replace(/fd_classname_dec_/ig, ''); } } if (inp.value.length == 0 || isNaN(inp.value) == true) { inp.value = 0; } obj = new incrementalInput(inp, range, increment, classInc, classDec); incremetalInputController.inputCollection.push(obj); } } } }; // Close and call anonymous function })(); addEvent(window, 'load', incremetalInputController.constructor, true);