r2585 - Spinner: Added support for hexadecimal or other bases via a new radix option, added padLe...
Author: btburnett3
Date: Sun May 17 15:05:21 2009
New Revision: 2585
Added:
branches/dev/spinner/demos/spinner/hexadecimal.html
Modified:
branches/dev/spinner/demos/spinner/index.html
branches/dev/spinner/ui/ui.spinner.js
Log:
Spinner: Added support for hexadecimal or other bases via a new radix
option, added padLength to left pad spinner with zeroes, added pageStep
option for page up/page down functionality, renamed options to reflect
HTML5 specifications
Added: branches/dev/spinner/demos/spinner/hexadecimal.html
==============================================================================
--- (empty file)
+++ branches/dev/spinner/demos/spinner/hexadecimal.html Sun May 17 15:05:21
2009
@@ -0,0 +1,34 @@
+<!doctype html>
+<html lang="en">
+<head>
+ <title>jQuery UI Spinner - Hexadecimal</title>
+ <link type="text/css" href="../../themes/base/ui.all.css"
rel="stylesheet" />
+ <script type="text/javascript" src="../../jquery-1.3.2.js"></script>
+ <script type="text/javascript"
src="../../external/mousewheel/jquery.mousewheel.min.js"></script>
+ <script type="text/javascript" src="../../ui/ui.core.js"></script>
+ <script type="text/javascript" src="../../ui/ui.spinner.js"></script>
+ <link type="text/css" href="../demos.css" rel="stylesheet" />
+ <script type="text/javascript">
+ $(function() {
+ $("#hexadecimal").spinner({radix: 16, padLength: 6, precision: 2,
step: '0.01'});
+ });
+ </script>
+</head>
+<body>
+
+<div class="demo">
+
+
+ <label for="hexadecimal">Hexadecimal spinner:</label>
+ <input id="hexadecimal" name="hexadecimal" value="0" />
+
+</div><!-- End demo -->
+
+<div class="demo-description">
+
+Example of a hexadecimal spinner.
+
+</div><!-- End demo-description -->
+
+</body>
+</html>
Modified: branches/dev/spinner/demos/spinner/index.html
==============================================================================
--- branches/dev/spinner/demos/spinner/index.html (original)
+++ branches/dev/spinner/demos/spinner/index.html Sun May 17 15:05:21 2009
@@ -10,6 +10,7 @@
<ul>
<li class="demo-config-on"><a href="default.html">Default
functionality</a></li>
<li><a href="donation.html">Donation</a></li>
+ <li><a href="hexadecimal.html">Hexadecimal</a></li>
<li><a href="latlong.html">Map</a></li>
<li><a href="list.html">List</a></li>
<li><a href="incremental.html">Incremental</a></li>
Modified: branches/dev/spinner/ui/ui.spinner.js
==============================================================================
--- branches/dev/spinner/ui/ui.spinner.js (original)
+++ branches/dev/spinner/ui/ui.spinner.js Sun May 17 15:05:21 2009
@@ -14,41 +14,67 @@
// shortcut constants
var hover = 'ui-state-hover',
- active= 'ui-state-active',
+ active = 'ui-state-active',
namespace = '.spinner';
$.widget('ui.spinner', {
_init: function() {
- var self = this;
-
+ var self = this,
+ validChars;
+
+ function parse(val) {
+ if ((val != null) && (typeof val == 'string'))
+ val = self._parseValue(val, self.options.radix,
self.options.groupSeparator, self.options.radixPoint);
+ return isNaN(val) ? null : val;
+ }
+
self._trigger('init', null, self.ui(null));
// initialize variables
- // this can't be initialized as part of the prototype because all
widgets would share the same object
+ // _curDelay can't be initialized as part of the prototype because all
widgets would share the same object
self._curDelay = {};
self.focused = false;
self.hovered = false;
// perform data bind on generic objects
- if (this.options.items != null && typeof this.options.items[0]
== 'object' && !this.element.is('input')) {
+ if (self.options.items != null && typeof self.options.items[0]
== 'object' && !self.element.is('input')) {
var data = this.options.items;
for (var i=0; i<data.length; i++) {
- this._addItem(data[i]);
+ self._addItem(data[i]);
}
}
-
- // check for decimals in steppinng and set _decimals as internal
- this._decimals = parseInt(this.options.decimals, 10);
- if (this.options.stepping.toString().indexOf('.') != -1 &&
this._decimals == 0) {
- var s = this.options.stepping.toString();
- this._decimals = s.slice(s.indexOf('.')+1, s.length).length;
+
+ // Create list of valid characters used to build regexs
+ validChars = '\\-\\' + self.options.radixPoint;
+ if (self.options.groupSeparator)
+ validChars += '\\' + self.options.groupSeparator;
+ if (self.options.radix < 10)
+ validChars += '0-' + self.options.radix;
+ else {
+ validChars += '0-9'
+ if (self.options.radix > 10)
+ validChars += 'a-' + String.fromCharCode('a'.charCodeAt(0) +
self.options.radix - 11);
+ }
+ self.validChars = validChars;
+
+ // Parse min, max, step, and pageStep for strings based on radix
+ self.options.min = parse(self.options.min);
+ self.options.max = parse(self.options.max);
+ self.options.step = parse(self.options.step);
+ self.options.pageStep = parse(self.options.pageStep);
+
+ // check for precision in steppinng and set _precision as internal
+ self._precision = parseInt(self.options.precision, 10);
+ if (self.options.step.toString().indexOf('.') != -1 && self._precision
== 0) {
+ var s = self.options.step.toString();
+ self._precision = s.slice(s.indexOf('.')+1, s.length).length;
}
-
+
//Initialize needed constants
self.element
.addClass('ui-spinner-box')
.attr('autocomplete', 'off') // switch off autocomplete in opera
- .width(this.options.width);
+ .width(self.options.width);
self._setValue( isNaN(self._getValue()) ? self.options.start :
self._getValue() );
@@ -58,9 +84,9 @@
.addClass('ui-spinner ui-widget ui-widget-content ui-corner-all')
// check for IE
.css({
- display: !$.support.opacity &&
$(this).css('display', 'inline-block') ? 'inline' : false
+ display: !$.support.opacity &&
$(self).css('display', 'inline-block') ? 'inline' : false
})
- .append('<button class="ui-spinner-up ui-state-default ui-corner-tr"
type="button"><span class="ui-icon
ui-icon-triangle-1-n">▲</span></button>')
+ .append('<button class="ui-spinner-up ui-state-default ui-corner-tr"
tabindex="-1"><span class="ui-icon
ui-icon-triangle-1-n">▲</span></button>')
.find('.ui-spinner-up')
.bind('mousedown', function(event) {
$(this).addClass(active);
@@ -72,37 +98,20 @@
.bind('mouseup', function(event) {
$(this).removeClass(active);
if (self.counter == 1) {
- self._up(event);
+ self._up(self.options.step, event);
}
self._mouseup(event);
})
// mousedown/mouseup capture first click, now handle second click
.bind('dblclick', function(event) {
- $(this).removeClass(active);
- self._up(event);
- self._mouseup(event);
- })
- .bind('keydown'+namespace, function(event) {
- var KEYS = $.ui.keyCode;
- if (event.keyCode == KEYS.SPACE || event.keyCode == KEYS.ENTER) {
- $(this).addClass(active);
- if (!self.counter) {
- self.counter = 1;
- }
- self._up.call(self, event);
- } else if (event.keyCode == KEYS.DOWN || event.keyCode == KEYS.RIGHT)
{
- self.element.siblings('.ui-spinner-down').focus();
- } else if (event.keyCode == KEYS.LEFT) {
- self.element.focus();
+ if ($.browser.msie) {
+ $(this).removeClass(active);
+ self._up(self.options.step, event);
+ self._mouseup(event);
}
})
- .bind('keyup'+namespace, function(event) {
- $(this).removeClass(active);
- self.counter = 0;
- self._trigger('change', event);
- })
.end()
- .append('<button class="ui-spinner-down ui-state-default ui-corner-br"
type="button"><span class="ui-icon
ui-icon-triangle-1-s">▼</span></button>')
+ .append('<button class="ui-spinner-down ui-state-default ui-corner-br"
tabindex="-1"><span class="ui-icon
ui-icon-triangle-1-s">▼</span></button>')
.find('.ui-spinner-down')
.bind('mousedown', function(event) {
$(this).addClass(active);
@@ -114,33 +123,18 @@
.bind('mouseup', function(event) {
$(this).removeClass(active);
if (self.counter == 1) {
- self._down();
+ self._down(self.options.step, event);
}
self._mouseup(event);
})
- // mousedown/mouseup capture first click, now handle second click
+ // mousedown/mouseup capture first click, now handle second click in IE
.bind('dblclick', function(event) {
- $(this).removeClass(active);
- self._down(event);
- self._mouseup(event);
- })
- .bind('keydown'+namespace, function(event) {
- var KEYS = $.ui.keyCode;
- if (event.keyCode == KEYS.SPACE || event.keyCode == KEYS.ENTER) {
- $(this).addClass(active);
- if (!self.counter) {
- self.counter = 1;
- }
- self._down.call(self, event);
- } else if (event.keyCode == KEYS.UP || event.keyCode == KEYS.LEFT) {
- self.element.siblings('.ui-spinner-up').focus();
+ if ($.browser.msie) {
+ $(this).removeClass(active);
+ self._down(self.options.step, event);
+ self._mouseup(event);
}
})
- .bind('keyup'+namespace, function(event) {
- $(this).removeClass(active);
- self.counter = 0;
- self._trigger('change', event);
- })
.end()
.hover(function() {
self.hovered = true;
@@ -190,7 +184,7 @@
.parent()
.height(height)
.end();
- self.options.stepping = 1;
+ self.options.step = 1;
self.options.min = 0;
self.options.max = self._items-1;
}
@@ -239,28 +233,31 @@
this._setValue(this._getValue());
this._constrain();
},
- _spin: function(d, event) {
+ _spin: function(d, step, event) {
if (this.disabled) {
return;
}
+
+ var value = this._getValue();
- if (isNaN(this._getValue())) {
- this._setValue(this.options.start);
+ if (isNaN(value)) {
+ value = 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._setValue(value + (d == 'up' ? 1:-1) *(this.options.incremental &&
this.counter > 100 ? (this.counter > 200 ? 100 : 10) : 1) * step);
this._animate(d);
this._constrain();
if (this.counter) {
this.counter++;
}
+
this._trigger('spin', event);
},
- _down: function(event) {
- this._spin('down', event);
+ _down: function(step, event) {
+ this._spin('down', step, event);
this._trigger('down', event);
},
- _up: function(event) {
- this._spin('up', event);
+ _up: function(step, event) {
+ this._spin('up', step, event);
this._trigger('up', event);
},
_mousedown: function(i, d, event) {
@@ -271,7 +268,7 @@
this.timer = 0;
}
this.timer = window.setInterval(function() {
- self[d](event);
+ self[d](self.options.step, event);
if (self.options.incremental && self.counter > 20) {
self._mousedown(20, d, event);
}
@@ -290,10 +287,16 @@
var KEYS = $.ui.keyCode;
if (event.keyCode == KEYS.UP) {
- this._up(event);
+ this._up(this.options.step, event);
}
if (event.keyCode == KEYS.DOWN) {
- this._down(event);
+ this._down(this.options.step, event);
+ }
+ if (event.keyCode == KEYS.PAGE_UP) {
+ this._up(this.options.pageStep, event);
+ }
+ if (event.keyCode == KEYS.PAGE_DOWN) {
+ this._down(this.options.pageStep, event);
}
if (event.keyCode == KEYS.HOME) {
//Home key goes to min, if defined, else to start
@@ -307,7 +310,7 @@
event.keyCode == KEYS.LEFT || event.keyCode == KEYS.RIGHT ||
event.keyCode == KEYS.PERIOD ||
event.keyCode == KEYS.NUMPAD_DECIMAL || event.keyCode ==
KEYS.NUMPAD_SUBTRACT ||
(event.keyCode >= 96 && event.keyCode <= 105) || // add support for
numeric keypad 0-9
- (/[0-9\-\.]/).test(String.fromCharCode(event.keyCode))) ? true : false;
+ (new RegExp('[' + this.validChars
+ ']', 'i').test(String.fromCharCode(event.keyCode)))) ? true : false;
},
_mousewheel: function(event, delta) {
// this = element, not widget, in event call
@@ -315,7 +318,7 @@
var self = $.data(this, 'spinner');
delta = ($.browser.opera ? -delta / Math.abs(delta) : delta);
- (delta > 0 ? self._up(event) : self._down(event));
+ self[delta > 0 ? '_up' : '_down'](self.options.step, event);
if (self.timeout) {
window.clearTimeout(self.timeout);
self.timeout = 0;
@@ -323,12 +326,23 @@
self.timeout = window.setTimeout(function(){self._trigger('change',
event);}, 400);
event.preventDefault();
},
+ _parseValue: function(val, radix, groupSeparator, radixPoint) {
+ // Because groupSeparator is included in the regex, we must replace it
independently
+ if (groupSeparator)
+ val = val.replace(groupSeparator, '');
+
+ val = val.replace(new RegExp('[^' + this.validChars
+ ']', 'gi'), '').split(radixPoint);
+
+ result = parseInt(val[0], radix);
+ if (val.length > 1)
+ result += parseInt(val[1], radix) / Math.pow(radix, val[1].length) *
+ // must test first character of val[0] for minus sign because -0 is
parsed as 0 in result
+ (val[0][0] == '-' ? -1 : 1);
+
+ return result;
+ },
_getValue: function() {
- var val = this.element.val().replace(this.options.point, '.');
- if (this.options.group === '.') {
- val = val.replace('.','');
- }
- return parseFloat(val.replace(/[^0-9\-\.]/g, ''));
+ return this._parseValue(this.element.val(), this.options.radix,
this.options.groupSeparator, this.options.radixPoint);
},
_setValue: function(newVal) {
if (isNaN(newVal)) {
@@ -336,8 +350,8 @@
}
this.element.val(
this.options.currency ?
- $.ui.spinner.format.currency(newVal, this.options.currency,
this.options.group, this.options.point) :
- $.ui.spinner.format.number(newVal, this._decimals, this.options.group,
this.options.point)
+ $.ui.spinner.format.currency(newVal, this.options.currency,
this.options.groupSeparator, this.options.radixPoint) :
+ $.ui.spinner.format.number(newVal, this._precision,
this.options.radix, this.options.groupSeparator, this.options.radixPoint,
this.options.padLength)
);
},
_animate: function(d) {
@@ -501,18 +515,25 @@
$.extend($.ui.spinner, {
version: "@VERSION",
defaults: {
- decimals: 0,
- stepping: 1,
+ precision: 0,
+ radix: 10,
+ padLength: 0,
+ max: null,
+ min: null,
+
+ step: 1,
+ pageStep: 5,
start: 0,
+
incremental: true,
mouseWheel: true,
currency: false,
+
format: '%',
- group: '',
- point: '.',
+ groupSeparator: '',
+ radixPoint: '.',
+
items: null,
- max: null,
- min: null,
width: 'auto',
autoHide: false
},
@@ -521,10 +542,23 @@
num = isNaN(num) ? 0 : num;
return (num !== Math.abs(num) ? '-' : '') + sym +
this.number(Math.abs(num), 2, group || ',', pt);
},
- number: function(num, dec, group, pt) {
- var regex = /(\d+)(\d{3})/;
- for (num = isNaN(num) ? 0 : parseFloat(num,10).toFixed(dec), num =
num.replace('.', pt); regex.test(num) && group;
num=num.replace(regex, '$1'+group+'$2'));
- return num;
+ number: function(num, dec, radix, group, pt, padLength) {
+ var whole = Math.floor(Math.abs(num)),
+ result = whole.toString(radix),
+ part = Math.floor(((Math.abs(num) - whole) * Math.pow(radix,
dec))).toString(radix),
+ regex = /(\d+)(\d{3})/;
+
+ while (regex.test(result) && group)
result=result.replace(regex, '$1'+group+'$2');
+
+ if (dec > 0) {
+ while (part.length < dec) part = '0' + part;
+ result += pt + part;
+ }
+
+ while (padLength && (result.length < padLength))
+ result = '0' + result;
+
+ return (num < 0 ? '-' : '') + result;
}
}
});