r3152 committed - spinner: removed readOnly option; fixed a load of bugs flagged from un...

r3152 committed - spinner: removed readOnly option; fixed a load of bugs flagged from un...


Revision: 3152
Author: pazu2k@gmail.com
Date: Thu Aug 27 08:58:51 2009
Log: spinner: removed readOnly option; fixed a load of bugs flagged from
unit tests; minor code refactor.
http://code.google.com/p/jquery-ui/source/detail?r=3152
Added:
/branches/dev/spinner/tests/visual/spinner/spinner_option_padding.html
/branches/dev/spinner/tests/visual/spinner/spinner_option_precision.html
Modified:
/branches/dev/spinner/tests/unit/spinner/spinner_core.js
/branches/dev/spinner/tests/unit/spinner/spinner_defaults.js
/branches/dev/spinner/tests/unit/spinner/spinner_options.js
/branches/dev/spinner/tests/visual/spinner/spinner.html
/branches/dev/spinner/tests/visual/spinner/spinner_option_readOnly.html
/branches/dev/spinner/ui/ui.spinner.js
=======================================
--- /dev/null
+++ /branches/dev/spinner/tests/visual/spinner/spinner_option_padding.html    
Thu Aug 27 08:58:51 2009
@@ -0,0 +1,24 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <title>Spinner Visual Test : Spinner option padding</title>
+    <link rel="stylesheet" href="../visual.css" type="text/css">
+    <link rel="stylesheet" href="../../../themes/base/ui.all.css"
type="text/css">
+    <script type="text/javascript" src="../../../jquery-1.3.2.js"></script>
+    <script type="text/javascript" src="../../../ui/ui.core.js"></script>
+    <script type="text/javascript" src="../../../ui/ui.spinner.js"></script>
+    <script type="text/javascript">
+    $(function() {
+        $('#spinner').spinner({ padding: 5 });
+        $('#spinner').spinner('option', 'padding', 4);
+    });
+    </script>
+</head>
+<body>
+<div class="ui-widget">
+
+    

<label>padded value:</label> <input id="spinner" type="text"
value="10">


+
+</div>
+</body>
+</html>
=======================================
--- /dev/null
+++
/branches/dev/spinner/tests/visual/spinner/spinner_option_precision.html    
Thu Aug 27 08:58:51 2009
@@ -0,0 +1,24 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <title>Spinner Visual Test : Spinner option precision</title>
+    <link rel="stylesheet" href="../visual.css" type="text/css">
+    <link rel="stylesheet" href="../../../themes/base/ui.all.css"
type="text/css">
+    <script type="text/javascript" src="../../../jquery-1.3.2.js"></script>
+    <script type="text/javascript" src="../../../ui/ui.core.js"></script>
+    <script type="text/javascript" src="../../../ui/ui.spinner.js"></script>
+    <script type="text/javascript">
+    $(function() {
+        $('#spinner').spinner({ precision: 4, value: 1.23456789 });
+        $('#spinner').spinner('option', 'precision', 2);
+    });
+    </script>
+</head>
+<body>
+<div class="ui-widget">
+
+    

<label>precision:</label> <input id="spinner" type="text"
value="10">


+
+</div>
+</body>
+</html>
=======================================
--- /branches/dev/spinner/tests/unit/spinner/spinner_core.js    Mon Aug 24
21:15:22 2009
+++ /branches/dev/spinner/tests/unit/spinner/spinner_core.js    Thu Aug 27
08:58:51 2009
@@ -204,7 +204,7 @@
    simulateKeyDownUp(el, $.ui.keyCode.HOME);
    equals(el.val(), -100);
-    el.spinner('options', 'min', -200);
+    el.spinner('option', 'min', -200);
    simulateKeyDownUp(el, $.ui.keyCode.HOME);
@@ -223,7 +223,7 @@
    simulateKeyDownUp(el, $.ui.keyCode.END);
    equals(el.val(), 100);
-    el.spinner('options', 'max', 200);
+    el.spinner('option', 'max', 200);
    simulateKeyDownUp(el, $.ui.keyCode.END);
=======================================
--- /branches/dev/spinner/tests/unit/spinner/spinner_defaults.js    Tue Jul 28
07:46:46 2009
+++ /branches/dev/spinner/tests/unit/spinner/spinner_defaults.js    Thu Aug 27
08:58:51 2009
@@ -17,7 +17,6 @@
    precision: 0,
    radix: 10,
    radixPoint: '.',
-    readOnly: null,
    spinnerClass: null,
    step: null,
    value: 0,
=======================================
--- /branches/dev/spinner/tests/unit/spinner/spinner_options.js    Tue Aug 25
11:17:52 2009
+++ /branches/dev/spinner/tests/unit/spinner/spinner_options.js    Thu Aug 27
08:58:51 2009
@@ -110,10 +110,8 @@
    equals(el.val(), "-$50.00", "Home key to min");
    for ( var i = 1 ; i<=120 ; i++ ) {
-        el.simulate("keydown",{keyCode:$.ui.keyCode.UP});
-    }
-
-    el.simulate("keyup",{keyCode:$.ui.keyCode.UP});
+        simulateKeyDownUp(el, $.ui.keyCode.UP);
+    }
    equals(el.val(), "-$14.00", "keydown 120 times");
});
@@ -307,21 +305,21 @@
    el.spinner('value', 1000);
    equals(el.val(), 100, "max constrained if value method is greater");
-    el.val(1000);
+    el.val(1000).blur();
    equals(el.val(), 100, "max constrained if manual entry");
});
test("min", function() {
    expect(3);
-    el = $("#spin").spinner({ max: -100, value: -1000 });
-    equals(el.val(), -100, "max constrained if value option is greater");
+    el = $("#spin").spinner({ min: -100, value: -1000 });
+    equals(el.val(), -100, "min constrained if value option is greater");
    el.spinner('value', -1000);
-    equals(el.val(), -100, "max constrained if value method is greater");
-
-    el.val(-1000);
-    equals(el.val(), -100, "max constrained if manual entry");
+    equals(el.val(), -100, "min constrained if value method is greater");
+
+    el.val(-1000).blur();
+    equals(el.val(), -100, "min constrained if manual entry");
});
test("mouseWheel", function() {
@@ -363,13 +361,13 @@
test("precision", function() {
    expect(2);
-    el = $("#spin").spinner({ precision: 2, value: 1.23456789 });
-
-    equals(el.val(), '1.23', "2 decimal places");
-
-    el.spinner('option', 'precision', 4);
-
-    equals(el.val(), '1.2345', "4 decimal places");
+    el = $("#spin").spinner({ precision: 4, value: 1.23456789 });
+
+    equals(el.val(), '1.2346', "4 decimal places");
+
+    el.spinner('option', 'precision', 2);
+
+    equals(el.val(), '1.23', "2 decimal places");
});
test("radix", function() {
@@ -405,32 +403,6 @@
    equals(el.val(), '-29,00', 'page down into negative space');
});
-test("readOnly", function() {
-    expect(5);
-
-    el = $('#spin').spinner({ readOnly: true, value: 0 });
-
-    upButton().trigger('mousedown').trigger('mouseup');
-
-    equals(el.val(), 0, 'mouse - value does not change on clicking up
button');
-
-    simulateKeyDownUp(el, $.ui.keyCode.UP);
-
-    equals(el.val(), 0, 'keyboard - value does not change on key UP');
-
-    el.spinner('stepUp');
-
-    equals(el.val(), 1, 'api - value changes on stepUp');
-
-    el.spinner('value', 100);
-
-    equals(el.val(), 100, 'api - value changes on calling the value method');
-
-    el.spinner('option', 'value', 200);
-
-    equals(el.val(), 200, 'api - value changes on setting option value');
-});
-
test("spinnerClass", function() {
    expect(3);
=======================================
--- /branches/dev/spinner/tests/visual/spinner/spinner.html    Mon Aug 17
08:28:27 2009
+++ /branches/dev/spinner/tests/visual/spinner/spinner.html    Thu Aug 27
08:58:51 2009
@@ -18,17 +18,23 @@
        // event callbacks
        $('#spinner2').spinner({
            start: function(event, ui) {
+                console.log(event, ui);
            },
            spin: function(event, ui) {
+                console.log(event, ui);
+                return false;
            },
            stop: function(event) {
+                console.log(event);
            },
            change: function(event) {
+                console.log(event);
            }
        });
        // hook via bind
        $('#spinner3').spinner().bind('spinstart spin spinstop spinchange',
function(event, ui) {
-        });
+
+        });
    });
    </script>
</head>
=======================================
--- /branches/dev/spinner/tests/visual/spinner/spinner_option_readOnly.html    
Thu Jul 30 21:01:26 2009
+++ /branches/dev/spinner/tests/visual/spinner/spinner_option_readOnly.html    
Thu Aug 27 08:58:51 2009
@@ -11,7 +11,7 @@
    $(function() {
        $('#spinner1').spinner();
-        $('#spinner2').spinner({ readOnly: true });
+        $('#spinner2').spinner();
    });
    </script>
@@ -20,7 +20,6 @@
<div class="ui-widget">
    

<label>HTML attribute readOnly:</label> <input id="spinner1"
type="text" readonly="readonly" value="100">


-    

<label>Spinner option readOnly:</label> <input id="spinner2"
type="text">


</div>
</body>
=======================================
--- /branches/dev/spinner/ui/ui.spinner.js    Mon Aug 24 07:32:07 2009
+++ /branches/dev/spinner/ui/ui.spinner.js    Thu Aug 27 08:58:51 2009
@@ -17,14 +17,15 @@
    active = 'ui-state-active',
    namespace = '.spinner',
    buttonRegex = /hide|auto|fast|slow|(\d+)/,
-    buttonDefault = 'show';
+    buttonDefault = 'show',
+    uiSpinnerClasses = 'ui-spinner ui-state-default ui-widget
ui-widget-content ui-corner-all ';
$.widget('ui.spinner', {
    _init: function() {
        this._initOptions();
-
-        this._value(this._value() || this.options.value);
-
+
+        this.value(this._parse(this.element.val() || this.options.value));
+
        this._draw();
        this._mousewheel();
@@ -32,6 +33,8 @@
        if (this.options.buttons !== buttonDefault) {
            this.buttons.hide();
        }
+
+        this._aria();
    },
    _initOptions: function() {
        var self = this,
@@ -39,7 +42,7 @@
        // parse min, max, step, and page based on radix
        // min, max and step pull from attributes if the option is set to null
-        $.each({ min: -Number.MAX_VALUE, max: Number.MAX_VALUE, step: 1},
+        $.each({ min: -Number.MAX_VALUE, max: Number.MAX_VALUE, step: 1 },
            function(option, defaultValue) {
                options[option] = self._parse(options[option] !== null
                    ? options[option]
@@ -50,24 +53,21 @@
        options.page = self._parse(options.page || 1);
-        options.readOnly = options.readOnly !== null
-            ? options.readOnly
-            : self.element.attr('readonly');
-
        // check for precision in stepping and set _precision as internal
-        self._precision = parseInt(options.precision, 10);
-
-        if (options.step.toString().indexOf('.') != -1 && self._precision === 0)
{
+        var precision = parseInt(options.precision, 10);
+
+        if (options.step.toString().indexOf('.') != -1 && precision === 0) {
            var s = options.step.toString();
-            self._precision = s.slice(s.indexOf('.')+1, s.length).length;
+            precision = s.slice(s.indexOf('.')+1, s.length).length;
        }
        // set currency options
        if (options.currency) {
-            this._precision = 2;
-            options.radix = 10,
+            precision = 2;
+            options.radix = 10;
            options.groupSeparator = options.groupSeparator || (options.radixPoint
=== ',' ? '' : ',');
        }
+        options.precision = precision;
    },
    _draw: function() {
        var self = this,
@@ -80,13 +80,9 @@
            .parent()
                // add buttons
                .append(self._buttonHtml())
-                // add aria properties
-                .attr('aria-valuemin',options.min)
-                .attr('aria-valuemax',options.max)
-                .attr('aria-valuenow',options.value)
                // add behaviours
                .hover(function() {
-                    if (!options.readOnly && !options.disabled) {
+                    if (!options.disabled) {
                        $(this).addClass(hover);
                    }
                    self.hovered = true;
@@ -122,20 +118,16 @@
                }
            })
            .bind('focus'+namespace, function() {
-                if (options.readOnly) {
-                    self.element.blur();
-                    return false;
-                }
                uiSpinner.addClass(active);
                self.focused = true;
            })
            .bind('blur'+namespace, function(event) {
+                self._value(self.element.val());
                if (!self.hovered) {
                    uiSpinner.removeClass(active);
                }
                self.focused = false;
-                self._cleanUp();
-            });
+            });
        // force width if passed through options
        if (options.width) {
@@ -155,7 +147,7 @@
                }
                self._repeat(null, $(this).hasClass('ui-spinner-up') ? 1 : -1, event);
-                if (!self.options.disabled && !self.options.readOnly) {
+                if (!self.options.disabled) {
                    $(this).addClass(active);
                    uiSpinner.addClass(active);
                }
@@ -171,7 +163,7 @@
                $(this).removeClass(active);
            })
            .hover(function() {
-                if (!self.options.disabled && !self.options.readOnly) {
+                if (!self.options.disabled) {
                    $(this).addClass(hover);
                }
            }, function(event) {
@@ -185,7 +177,7 @@
        self.uiSpinner = uiSpinner;
    },
    _uiSpinnerHtml: function() {
-        return '<div role="spinbutton" class="ui-spinner ui-state-default
ui-widget ui-widget-content ui-corner-all ' +
+        return '<div role="spinbutton" class="' + uiSpinnerClasses +
                (this.options.spinnerClass || '') +
                ' ui-spinner-' + this.options.dir +
                '"></div>';
@@ -196,21 +188,8 @@
                '<a class="ui-spinner-button ui-spinner-down ui-state-default
ui-corner-b' + this.options.dir.substr(-1,1) +
                '"><span class="ui-spinner-button-inner"><span class="ui-icon
ui-icon-triangle-1-s">&#9660;</span></span></a>';
    },
-    _constrain: function() {
-        var value = this._value();
-        if (value < this.options.min) {
-            this._value(this.options.min);
-        }
-        if (value > this.options.max) {
-            this._value(this.options.max);
-        }
-    },
-    _cleanUp: function() {
-        this._value(this._value());
-        this._constrain();
-    },
    _start: function(event) {
-        if (!this.spinning && !this.options.readOnly && this._trigger('start',
event, { value: this.value()}) !== false) {
+        if (!this.spinning && this._trigger('start', event, { value:
this.value()}) !== false) {
            if (!this.counter) {
                this.counter = 1;
            }
@@ -220,7 +199,7 @@
        return false
    },
    _spin: function(step, event) {
-        if (this.options.disabled || this.options.readOnly) {
+        if (this.options.disabled) {
            return;
        }
        if (!this.counter) {
@@ -236,7 +215,6 @@
        // cancelable
        if (this._trigger('spin', event, { value: newVal }) !== false) {
            this._value(newVal);
-            this._constrain();
            this.counter++;
        }
    },
@@ -289,6 +267,10 @@
            case KEYS.NUMPAD_DECIMAL:
            case KEYS.NUMPAD_SUBTRACT:
                return true;
+
+            case KEYS.ENTER:
+                this.value(this.element.val());
+                return true;
            default:
                if ((event.keyCode >= 96 && event.keyCode <= 105) || // numeric keypad
0-9
@@ -321,48 +303,65 @@
            });
        }
    },
-    _value: function(newVal) {
+    _value: function(newValue) {
        if (!arguments.length) {
-            return this._parse(this.element.val());
-        }
-
-        this._format(newVal);
-        this._setData('value', newVal);
-        this.uiSpinner && this.uiSpinner.attr('aria-valuenow', this.value());
+            return this.options.value;
+        }
+        this._setData('value', newValue);
    },
    _setData: function(key, value) {
        switch (key) {
            case 'buttons':
                this._hide();
                break;
+            case 'value':
+                value = this._parse(value);
+                if (value < this.options.min) {
+                    value = this.options.min;
+                }
+                if (value > this.options.max) {
+                    value = this.options.max;
+                }
+                break;
+            case 'spinnerClass':
+                this.uiSpinner
+                    .removeClass(this.options.spinnerClass)
+                    .addClass(uiSpinnerClasses + value);
+                break;
+        }
+
+        $.widget.prototype._setData.call(this, key, value);
+
+        this._afterSetData(key, value);
+        this._aria();
+    },
+    _afterSetData: function(key, value) {
+        switch(key) {
            case 'max':
            case 'min':
            case 'step':
-                if (this.options[key] != null) {
+                if (value != null) {
                    // write attributes back to element if original exist
                    if (this.element.attr(key)) {
                        this.element.attr(key, value);
                    }
-                    // add aria properties
-                    if (/min|max/.test(key)) {
-                        this.element.parent().attr('aria-value'+key, value);
-                    }
-                }
-                break;
-            case 'value':
-                this._format(value);
+                }
                break;
            case 'width':
                this.element.width(value);
                break;
-            case 'spinnerClass':
-                this.uiSpinner
-                    .removeClass(this.options.spinnerClass)
-                    .addClass(value);
+            case 'precision':
+            case 'value':
+                this._format(this._parse(this.options.value));
                break;
        }
-
-        $.widget.prototype._setData.call(this, key, value);
+    },
+    _aria: function() {
+        this.uiSpinner
+            && this.uiSpinner
+                .attr('aria-valuemin', this.options.min)
+                .attr('aria-valuemax', this.options.max)
+                .attr('aria-valuenow', this.value());
    },
    _validChars: function() {
        var radix = parseInt(this.options.radix);
@@ -394,10 +393,11 @@
        var regex = /(\d+)(\d{3})/,
            options = this.options,
            sym = options.currency || '',
-            dec = this._precision,
+            dec = options.precision,
            radix = options.radix,
            group = options.groupSeparator,
-            pt = options.radixPoint;
+            pt = options.radixPoint,
+            neg = num < 0 ? '-' : '';
        for (
            num = (
@@ -414,9 +414,8 @@
        result = num.replace('-','');
        while (options.padding && (result.length < options.padding)) {
            result = '0' + result;
-        }
-
-        this.element.val((num < 0 ? '-' : '') + sym + result);
+        }
+        this.element.val(neg + sym + result);
    },
    _hide: function(hide) {
        if (this.options.buttons === buttonDefault) {
@@ -439,7 +438,7 @@
            self.buttons.animate({opacity: hide ? 'hide' : 'show'}, speed);
        }, 200);
    },
-
+
    destroy: function() {
        if ($.fn.mousewheel) {
            this.element.unmousewheel();
@@ -514,7 +513,6 @@
        precision: 0,
        radix: 10,
        radixPoint: '.',
-        readOnly: null,
        spinnerClass: null,
        step: null,
        value: 0,