diff options
author | Ca-Phun Ung <pazu2k@gmail.com> | 2008-08-19 07:18:04 +0000 |
---|---|---|
committer | Ca-Phun Ung <pazu2k@gmail.com> | 2008-08-19 07:18:04 +0000 |
commit | 198d809f9bb8aa5a20181d8b4d0a2f58bbcc4179 (patch) | |
tree | 37a8a6f6e571021cb2fe03f2836f4dca5fb3472f /ui/ui.spinner.js | |
parent | b4e2e0e9ca4d0993920baba4cc0f50cba4362323 (diff) | |
download | jquery-ui-198d809f9bb8aa5a20181d8b4d0a2f58bbcc4179.tar.gz jquery-ui-198d809f9bb8aa5a20181d8b4d0a2f58bbcc4179.zip |
Added enhancements to ui.spinner as seen at http://yelotofu.com/labs/jquery/UI/spinner/spinner.html
Enhancements include:
- removal of all hardcoded styling for better theming capability
- visual test page made more appealing supporting browser zooming
- added utility functions to disable, enable and destroy ui.spinner
- up/down buttons listens to more mouse and keyboard events
- support for decimal and currency format
- ui.spinner now restricts input on keydown
- cleanup occurs when the input textbox loses focus. this seems to be a better approach for future scalability
Diffstat (limited to 'ui/ui.spinner.js')
-rw-r--r-- | ui/ui.spinner.js | 294 |
1 files changed, 231 insertions, 63 deletions
diff --git a/ui/ui.spinner.js b/ui/ui.spinner.js index 4bcb9e843..5d322bbc1 100644 --- a/ui/ui.spinner.js +++ b/ui/ui.spinner.js @@ -12,127 +12,295 @@ */
(function($) {
-$.widget("ui.spinner", {
+$.widget('ui.spinner', {
_init: function() {
-
+ if($.data(this.element[0], 'spinner')) return;
+
+ // check for decimals in steppinng and set _decimals as internal (needs cleaning up)
+ var decimals = 0;
+ if (this.options.stepping.toString().indexOf('.') != -1) {
+ var s = this.options.stepping.toString();
+ decimals = s.slice(s.indexOf('.')+1, s.length).length;
+ }
+ $.extend(this.options, {
+ _decimals: decimals
+ });
+
//Initialize needed constants
var self = this;
- this.element.addClass("ui-spinner");
- this.element[0].value = this.options.start;
+ this.element
+ .addClass('ui-spinner-box')
+ .attr('autocomplete', 'off'); // switch off autocomplete in opera
+
+ this._setValue( isNaN(this._getValue()) ? this.options.start : this._getValue() );
- var pickerHeight = this.element.innerHeight() / 2 - parseInt(this.element.css("borderTopWidth"),10) - 2;
this.element
- .wrap("<div>")
+ .wrap('<div>')
.parent()
- .css({
- position: this.element.css("position") == "static" ? "relative" : this.element.css("position"),
- left: this.element.css("left"),
- top: this.element.css("top"),
- width: this.element.outerWidth(),
- height: this.element.outerHeight()
- })
- .css("float", this.element.css("float"))
- .prepend('<div class="ui-spinner-up"></div>')
- .find("div.ui-spinner-up")
- .bind("mousedown", function() { if(!self.counter) self.counter = 1; self._mousedown(100, "_up"); })
- .bind("mouseup", function(e) { if(self.counter == 1) self._up(); self.counter = 0; if(self.timer) window.clearInterval(self.timer); self.element[0].focus(); self._propagate("change", e); })
- .bind("dblclick", function(e) { self._up(); }) // mousedown/mouseup capture first click, now handle second click
- .css({ height: pickerHeight, top: parseInt(this.element.css("borderTopWidth"),10)+1, right: parseInt(this.element.css("borderRightWidth"),10)+1 })
+ .addClass('ui-spinner')
+ .append('<button class="ui-spinner-up">▲</button>')
+ .find('.ui-spinner-up')
+ .bind('mousedown', function(e) {
+ $(this).addClass('ui-spinner-pressed');
+ if(!self.counter) self.counter = 1;
+ self._mousedown(100, '_up', e);
+ })
+ .bind('mouseup', function(e) {
+ $(this).removeClass('ui-spinner-pressed');
+ if(self.counter == 1) self._up(e);
+ self._mouseup(e);
+ })
+ .bind('mouseout', function(e) {
+ $(this).removeClass('ui-spinner-pressed');
+ self._mouseup(e);
+ })
+ // mousedown/mouseup capture first click, now handle second click
+ .bind('dblclick', function(e) {
+ $(this).removeClass('ui-spinner-pressed');
+ self._up(e);
+ })
+ .bind('keydown.spinner', function(e) {
+ var KEYS = $.ui.spinner.keys;
+ if (e.keyCode == KEYS.SPACE || e.keyCode == KEYS.RETURN) {
+ $(this).addClass('ui-spinner-pressed');
+ if(!self.counter) self.counter = 1;
+ self._up.call(self, e);
+ } else if (e.keyCode == KEYS.DOWN || e.keyCode == KEYS.RIGHT) {
+ self.element.siblings('.ui-spinner-down').focus();
+ } else if (e.keyCode == KEYS.LEFT) {
+ self.element.focus();
+ }
+ })
+ .bind('keyup.spinner', function(e) {
+ $(this).removeClass('ui-spinner-pressed');
+ self.counter = 0;
+ self._propagate('change', e);
+ })
.end()
- .append('<div class="ui-spinner-down"></div>')
- .find("div.ui-spinner-down")
- .bind("mousedown", function() { if(!self.counter) self.counter = 1; self._mousedown(100, "_down"); })
- .bind("mouseup", function(e) { if(self.counter == 1) self._down(); self.counter = 0; if(self.timer) window.clearInterval(self.timer); self.element[0].focus(); self._propagate("change", e); })
- .bind("dblclick", function(e) { self._down(); }) // mousedown/mouseup capture first click, now handle second click
- .css({ height: pickerHeight, bottom: parseInt(this.element.css("borderBottomWidth"),10)+1, right: parseInt(this.element.css("borderRightWidth"),10)+1 })
- .end()
- ;
+ .append('<button class="ui-spinner-down">▼</button>')
+ .find('.ui-spinner-down')
+ .bind('mousedown', function(e) {
+ $(this).addClass('ui-spinner-pressed');
+ if(!self.counter) self.counter = 1;
+ self._mousedown(100, '_down', e);
+ })
+ .bind('mouseup', function(e) {
+ $(this).removeClass('ui-spinner-pressed');
+ if(self.counter == 1) self._down();
+ self._mouseup(e);
+ })
+ .bind('mouseout', function(e) {
+ $(this).removeClass('ui-spinner-pressed');
+ self._mouseup(e);
+ })
+ // mousedown/mouseup capture first click, now handle second click
+ .bind('dblclick', function(e) {
+ $(this).removeClass('ui-spinner-pressed');
+ self._down(e);
+ })
+ .bind('keydown.spinner', function(e) {
+ var KEYS = $.ui.spinner.keys;
+ if (e.keyCode == KEYS.SPACE || e.keyCode == KEYS.RETURN) {
+ $(this).addClass('ui-spinner-pressed');
+ if(!self.counter) self.counter = 1;
+ self._down.call(self, e);
+ } else if (e.keyCode == KEYS.UP || e.keyCode == KEYS.LEFT) {
+ self.element.siblings('.ui-spinner-up').focus();
+ }
+ })
+ .bind('keyup.spinner', function(e) {
+ $(this).removeClass('ui-spinner-pressed');
+ self.counter = 0;
+ self._propagate('change', e);
+ })
+ .end();
this.element
- .bind("keydown.spinner", function(e) {
+ .bind('keydown.spinner', function(e) {
if(!self.counter) self.counter = 1;
- self._keydown.call(self, e);
+ return self._keydown.call(self, e);
})
- .bind("keyup.spinner", function(e) {
+ .bind('keyup.spinner', function(e) {
self.counter = 0;
- self._cleanUp();
- self._propagate("change", e);
+ self._propagate('change', e);
})
- ;
+ .bind('blur.spinner', function(e) {
+ self._cleanUp()
+ });
+
if ($.fn.mousewheel) {
- this.element.mousewheel(function(e, delta) { self._mousewheel(e, delta); });
+ this.element.mousewheel(function(e, delta) {
+ self._mousewheel(e, delta);
+ });
}
-
},
- plugins: {},
+
_constrain: function() {
- if(this.options.min != undefined && this.element[0].value < this.options.min) this.element[0].value = this.options.min;
- if(this.options.max != undefined && this.element[0].value > this.options.max) this.element[0].value = this.options.max;
+ if(this.options.min != undefined && this._getValue() < this.options.min) this._setValue(this.options.min);
+ if(this.options.max != undefined && this._getValue() > this.options.max) this._setValue(this.options.max);
},
_cleanUp: function() {
- this.element[0].value = this.element[0].value.replace(/[^0-9\-]/g, '');
+ this._setValue(this._getValue());
this._constrain();
},
- _spin: function(d ,e) {
- if(isNaN(parseInt(this.element[0].value,10))) this.element[0].value = this.options.start;
- this.element[0].value = parseFloat(this.element[0].value) + ( d == "up" ? 1 : -1 ) * (this.options.incremental && this.counter > 100 ? (this.counter > 200 ? 100 : 10) : 1) * this.options.stepping;
+ _spin: function(d, e) {
+ if (this.disabled) return;
+
+ if(isNaN(this._getValue())) this._setValue(this.options.start);
+ this._setValue(this._getValue() + (d == 'up' ? 1:-1) * (this.options.incremental && this.counter > 100 ? (this.counter > 200 ? 100 : 10) : 1) * this.options.stepping);
this._constrain();
if(this.counter) this.counter++;
- this._propagate("spin", e);
+ this._propagate('spin', e);
+
},
_down: function(e) {
- this._spin("down", e);
+ this._spin('down', e);
+ this._propagate('down', e);
},
_up: function(e) {
- this._spin("up", e);
+ this._spin('up', e);
+ this._propagate('up', e);
},
- _mousedown: function(i, d) {
+ _mousedown: function(i, d, e) {
var self = this;
i = i || 100;
if(this.timer) window.clearInterval(this.timer);
this.timer = window.setInterval(function() {
- self[d]();
- if(self.counter > 20) self._mousedown(20, d);
+ self[d](e);
+ if(self.counter > 20) self._mousedown(20, d, e);
}, i);
},
+ _mouseup: function(e) {
+ this.counter = 0;
+ if(this.timer) window.clearInterval(this.timer);
+ this.element[0].focus();
+ this._propagate('change', e);
+ },
_keydown: function(e) {
- if(e.keyCode == 38 || e.keyCode == 39) this._up(e);
- if(e.keyCode == 40 || e.keyCode == 37) this._down(e);
- if(e.keyCode == 36) this.element[0].value = this.options.min || this.options.start; //Home key goes to min, if defined, else to start
- if(e.keyCode == 35 && this.options.max != undefined) this.element[0].value = this.options.max; //End key goes to maximum
+ var KEYS = $.ui.spinner.keys;
+
+ if(e.keyCode == KEYS.UP) this._up(e);
+ if(e.keyCode == KEYS.DOWN) this._down(e);
+ if(e.keyCode == KEYS.HOME) this._setValue(this.options.min || this.options.start); //Home key goes to min, if defined, else to start
+ if(e.keyCode == KEYS.END && this.options.max != undefined) this._setValue(this.options.max); //End key goes to maximum
+ return (e.keyCode == KEYS.TAB || e.keyCode == KEYS.BACKSPACE ||
+ e.keyCode == KEYS.LEFT || e.keyCode == KEYS.RIGHT || e.keyCode == KEYS.PERIOD ||
+ (/[0-9\-\.]/).test(String.fromCharCode(e.keyCode))) ? true : false;
},
_mousewheel: function(e, delta) {
delta = ($.browser.opera ? -delta / Math.abs(delta) : delta);
delta > 0 ? this._up(e) : this._down(e);
e.preventDefault();
},
+ _getValue: function() {
+ return parseFloat(this.element[0].value.replace(/[^0-9\-\.]/g, ''));
+ },
+ _setValue: function(newVal) {
+ if(isNaN(newVal)) newVal = this.options.start;
+ this.element[0].value = (
+ this.options.currency ?
+ $.ui.spinner.format.currency(newVal, this.options.currency) :
+ $.ui.spinner.format.number(newVal, this.options._decimals)
+ );
+ },
+
+
+ plugins: {},
ui: function(e) {
return {
instance: this,
options: this.options,
- element: this.element
+ element: this.element,
+ value: this._getValue()
};
},
_propagate: function(n,e) {
$.ui.plugin.call(this, n, [e, this.ui()]);
- return this.element.triggerHandler(n == "spin" ? n : "spin"+n, [e, this.ui()], this.options[n]);
+ return this.element.triggerHandler(n == 'spin' ? n : 'spin'+n, [e, this.ui()], this.options[n]);
},
destroy: function() {
if(!$.data(this.element[0], 'spinner')) return;
+
this.element
- .removeClass("ui-spinner ui-spinner-disabled")
- .removeData("spinner")
- .unbind(".spinner");
+ .removeClass('ui-spinner-box')
+ .removeAttr('disabled')
+ .removeData('spinner')
+ .unbind('.spinner')
+ .siblings()
+ .remove()
+ .end()
+ .parent()
+ .removeClass('ui-spinner ui-spinner-disabled')
+ .before(this.element.clone())
+ .remove()
+ .end();
+
if ($.fn.mousewheel) {
this.element.unmousewheel();
}
+ },
+ enable: function() {
+ this.element
+ .removeAttr('disabled')
+ .siblings()
+ .removeAttr('disabled')
+ .parent()
+ .removeClass('ui-spinner-disabled');
+ this.disabled = false;
+ },
+ disable: function() {
+ this.element
+ .attr('disabled', true)
+ .siblings()
+ .attr('disabled', true)
+ .parent()
+ .addClass('ui-spinner-disabled');
+ this.disabled = true;
}
});
-$.ui.spinner.defaults = {
- stepping: 1,
- start: 0,
- incremental: true
-};
+$.extend($.ui.spinner, {
+ defaults: {
+ stepping: 1,
+ start: 0,
+ incremental: true,
+ currency: false
+ },
+ format: {
+ number: function(num, dec) {
+ return this.round(num, dec);
+ },
+ currency: function(num, sym) {
+ return (num !== Math.abs(num) ? '-' : '') + sym + this.round(Math.abs(num), 2);
+ },
+ round: function(num, dec) {
+ if (dec > 0) {
+ var s = num + ((num.toString().indexOf('.') == -1) ? '.' : '') + '0000000001';
+ s = s.substr(0, s.indexOf('.')+1+dec);
+ } else {
+ var s = Math.round(num);
+ }
+ return s;
+ }
+ },
+ keys: {
+ BACKSPACE: 8,
+ TAB: 9,
+ RETURN: 13,
+ ESC: 27,
+ SPACE: 32,
+ PAGEUP: 33,
+ PAGEDOWN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ DEL: 46,
+ COMMA: 188,
+ PERIOD: 190
+ }
+});
})(jQuery);
|