diff --git a/demos/spinner/time.html b/demos/spinner/time.html index 7fc1e26ce..175407f4a 100644 --- a/demos/spinner/time.html +++ b/demos/spinner/time.html @@ -24,13 +24,17 @@ _parse: function( value ) { if ( typeof value === "string" ) { + // already a timestamp + if ( Number( value ) == value ) { + return Number( value ); + } return +Globalize.parseDate( value ); } return value; }, - _format: function() { - return Globalize.format( new Date(this.options.value), "t" ); + _format: function( value ) { + return Globalize.format( new Date(value), "t" ); } }); diff --git a/tests/unit/spinner/spinner_core.js b/tests/unit/spinner/spinner_core.js index 1c2b7ae17..57b6b3320 100644 --- a/tests/unit/spinner/spinner_core.js +++ b/tests/unit/spinner/spinner_core.js @@ -4,9 +4,8 @@ module( "spinner: core" ); test( "keydown UP on input, increases value not greater than max", function() { expect( 5 ); - var element = $( "#spin" ).spinner({ + var element = $( "#spin" ).val( 70 ).spinner({ max: 100, - value: 70, step: 10 }); @@ -24,9 +23,8 @@ test( "keydown UP on input, increases value not greater than max", function() { test( "keydown DOWN on input, decreases value not less than min", function() { expect( 5 ); - var element = $( "#spin" ).spinner({ + var element = $( "#spin" ).val( 50 ).spinner({ min: 20, - value: 50, step: 10 }); @@ -44,9 +42,8 @@ test( "keydown DOWN on input, decreases value not less than min", function() { test( "keydown PAGE_UP on input, increases value not greater than max", function() { expect( 5 ); - var element = $( "#spin" ).spinner({ + var element = $( "#spin" ).val( 70 ).spinner({ max: 100, - value: 70, page: 10 }); @@ -64,9 +61,8 @@ test( "keydown PAGE_UP on input, increases value not greater than max", function test( "keydown PAGE_DOWN on input, decreases value not less than min", function() { expect( 5 ); - var element = $( "#spin" ).spinner({ + var element = $( "#spin" ).val( 50 ).spinner({ min: 20, - value: 50, page: 10 }); @@ -84,9 +80,8 @@ test( "keydown PAGE_DOWN on input, decreases value not less than min", function( test( "mouse click on up button, increases value not greater than max", function() { expect( 3 ); - var element = $( "#spin" ).spinner({ - max: 20, - value: 18 + var element = $( "#spin" ).val( 18 ).spinner({ + max: 20 }), button = element.spinner( "widget" ).find( ".ui-spinner-up" ); @@ -100,9 +95,8 @@ test( "mouse click on up button, increases value not greater than max", function test( "mouse click on up button, increases value not greater than max", function() { expect( 3 ); - var element = $( "#spin" ).spinner({ - min: 0, - value: 2 + var element = $( "#spin" ).val( 2 ).spinner({ + min: 0 }), button = element.spinner( "widget" ).find( ".ui-spinner-down" ); @@ -137,10 +131,9 @@ test( "mousewheel on input", function() { }); test( "reading HTML5 attributes", function() { - expect( 8 ); + expect( 6 ); var markup = "", element = $( markup ).spinner(); - equal( element.spinner( "option", "value" ), 5, "value from markup" ); equal( element.spinner( "option", "min" ), -100, "min from markup" ); equal( element.spinner( "option", "max" ), 100, "max from markup" ); equal( element.spinner( "option", "step" ), 2, "step from markup" ); @@ -148,10 +141,8 @@ test( "reading HTML5 attributes", function() { element = $( markup ).spinner({ min: -200, max: 200, - value: 20, step: 5 }); - equal( element.spinner( "option", "value" ), 20, "value from options" ); equal( element.spinner( "option", "min" ), -200, "min from options" ); equal( element.spinner( "option", "max" ), 200, "max from options" ); equal( element.spinner( "option", "step" ), 5, "stop from options" ); @@ -159,7 +150,7 @@ test( "reading HTML5 attributes", function() { test( "ARIA attributes", function() { expect( 7 ); - var element = $( "#spin" ).spinner({ min: -5, max: 5, value: 2 }); + var element = $( "#spin" ).val( 2 ).spinner({ min: -5, max: 5 }); equal( element.attr( "role" ), "spinbutton", "role" ); equal( element.attr( "aria-valuemin" ), -5, "aria-valuemin" ); @@ -185,17 +176,22 @@ test( "focus text field when pressing button", function() { ok( element[ 0 ] === document.activeElement, "focused after" ); }); +test( "don't clear invalid value on blur", function() { + expect( 1 ); + var element = $( "#spin" ).spinner(); + element.focus().val( "a" ).blur(); + equal( element.val(), "a" ); +}); + test( "precision", function() { expect( 2 ); - var element = $( "#spin" ).spinner({ - value: .05, + var element = $( "#spin" ).val( .05 ).spinner({ step: .0001 }); element.spinner( "stepUp" ); equal( element.val(), "0.0501", "precision from step" ); - element.spinner( "option", { - value: 1.05, + element.val( 1.05 ).spinner( "option", { step: 1 }); element.spinner( "stepDown" ); diff --git a/tests/unit/spinner/spinner_defaults.js b/tests/unit/spinner/spinner_defaults.js index 18949ff90..f155a658e 100644 --- a/tests/unit/spinner/spinner_defaults.js +++ b/tests/unit/spinner/spinner_defaults.js @@ -7,7 +7,6 @@ commonWidgetTests( "spinner", { numberFormat: null, page: 10, step: 1, - value: 0, // callbacks change: null, diff --git a/tests/unit/spinner/spinner_events.js b/tests/unit/spinner/spinner_events.js index e9f5da1ce..e43ba3365 100644 --- a/tests/unit/spinner/spinner_events.js +++ b/tests/unit/spinner/spinner_events.js @@ -129,24 +129,28 @@ test( "change", function() { }); } + element.focus(); shouldChange( false, "key UP, before blur" ); spinner_simulateKeyDownUp( element, $.ui.keyCode.UP ); shouldChange( true, "blur after key UP" ); element.blur(); + element.focus(); shouldChange( false, "key DOWN, before blur" ); spinner_simulateKeyDownUp( element, $.ui.keyCode.DOWN ); shouldChange( true, "blur after key DOWN" ); element.blur(); + element.focus(); shouldChange( false, "key PAGE_UP, before blur" ); spinner_simulateKeyDownUp( element, $.ui.keyCode.PAGE_UP ); shouldChange( true, "blur after key PAGE_UP" ); element.blur(); + element.focus(); shouldChange( false, "key PAGE_DOWN, before blur" ); spinner_simulateKeyDownUp( element, $.ui.keyCode.PAGE_DOWN ); - shouldChange( true, "key PAGE_DOWN" ); + shouldChange( true, "blur after key PAGE_DOWN" ); element.blur(); shouldChange( false, "many keys, before blur" ); diff --git a/tests/unit/spinner/spinner_methods.js b/tests/unit/spinner/spinner_methods.js index 29494f9cc..fbfcf1bb3 100644 --- a/tests/unit/spinner/spinner_methods.js +++ b/tests/unit/spinner/spinner_methods.js @@ -11,7 +11,7 @@ test( "destroy", function() { test( "disable", function() { expect( 14 ); - var element = $( "#spin" ).spinner({ value: 2 }), + var element = $( "#spin" ).val( 2 ).spinner(), wrapper = $( "#spin" ).spinner( "widget" ); ok( !wrapper.hasClass( "ui-spinner-disabled" ), "before: wrapper does not have ui-spinner-disabled class" ); @@ -71,9 +71,8 @@ test( "enable", function() { test( "pageDown", function() { expect( 4 ); - var element = $( "#spin" ).spinner({ + var element = $( "#spin" ).val( -12 ).spinner({ page: 20, - value: -12, min: -100 }); @@ -92,9 +91,8 @@ test( "pageDown", function() { test( "pageUp", function() { expect( 4 ); - var element = $( "#spin" ).spinner({ + var element = $( "#spin" ).val( 12 ).spinner({ page: 20, - value: 12, max: 100 }); @@ -113,9 +111,8 @@ test( "pageUp", function() { test( "stepDown", function() { expect( 4 ); - var element = $( "#spin" ).spinner({ + var element = $( "#spin" ).val( 0 ).spinner({ step: 2, - value: 0, min: -15 }); @@ -134,9 +131,8 @@ test( "stepDown", function() { test( "stepUp", function() { expect( 4 ); - var element = $( "#spin" ).spinner({ + var element = $( "#spin" ).val( 0 ).spinner({ step: 2, - value: 0, max: 15 }); @@ -155,7 +151,7 @@ test( "stepUp", function() { test( "value", function() { expect( 2 ); - var element = $( "#spin" ).spinner({ value: 0 }); + var element = $( "#spin" ).val( 0 ).spinner(); element.spinner( "value", 10 ); equals( element.val(), 10, "change value via value method" ); diff --git a/tests/unit/spinner/spinner_options.js b/tests/unit/spinner/spinner_options.js index 30155e755..647455fe5 100644 --- a/tests/unit/spinner/spinner_options.js +++ b/tests/unit/spinner/spinner_options.js @@ -3,30 +3,27 @@ module( "spinner: options" ); test( "numberFormat, number", function() { - expect( 1 ); - var element = $( "#spin" ).spinner({ - value: "1", - numberFormat: "n" - }); - equal( element.val(), "1.00", "n" ); + expect( 2 ); + var element = $( "#spin" ).val( 0 ).spinner({ numberFormat: "n" }); + equal( element.val(), "0.00", "formatted on init" ); + element.spinner( "stepUp" ); + equal( element.val(), "1.00", "formatted after step" ); }); test( "numberFormat, number, simple", function() { - expect( 1 ); - var element = $( "#spin" ).spinner({ - value: "1", - numberFormat: "n0" - }); - equal( element.val(), "1", "n0" ); + expect( 2 ); + var element = $( "#spin" ).val( 0 ).spinner({ numberFormat: "n0" }); + equal( element.val(), "0", "formatted on init" ); + element.spinner( "stepUp" ); + equal( element.val(), "1", "formatted after step" ); }); test( "numberFormat, currency", function() { - expect( 1 ); - var element = $( "#spin" ).spinner({ - value: "1", - numberFormat: "C" - }); - equal( element.val(), "$1.00", "C" ); + expect( 2 ); + var element = $( "#spin" ).val( 0 ).spinner({ numberFormat: "C" }); + equal( element.val(), "$0.00", "formatted on init" ); + element.spinner( "stepUp" ); + equal( element.val(), "$1.00", "formatted after step" ); }); /* TODO figure out how to test this properly @@ -69,32 +66,31 @@ test("incremental - true (default)", function() { test( "max", function() { expect( 3 ); - var element = $( "#spin" ).spinner({ max: 100, value: 1000 }); - equals( element.val(), 100, "max constrained if value option is greater" ); + var element = $( "#spin" ).val( 1000 ).spinner({ max: 100 }); + equals( element.val(), 1000, "value not constrained on init" ); element.spinner( "value", 1000 ); equals( element.val(), 100, "max constrained if value method is greater" ); element.val( 1000 ).blur(); - equals( element.val(), 100, "max constrained if manual entry" ); + equals( element.val(), 1000, "max not constrained if manual entry" ); }); test( "min", function() { expect( 3 ); - var element = $( "#spin" ).spinner({ min: -100, value: -1000 }); - equals( element.val(), -100, "min constrained if value option is greater" ); + var element = $( "#spin" ).val( -1000 ).spinner({ min: -100 }); + equals( element.val(), -1000, "value not constrained on init" ); element.spinner( "value", -1000 ); equals( element.val(), -100, "min constrained if value method is greater" ); element.val( -1000 ).blur(); - equals( element.val(), -100, "min constrained if manual entry" ); + equals( element.val(), -1000, "min not constrained if manual entry" ); }); test( "step, 2", function() { - expect( 4 ); - var element = $( "#spin" ).spinner({ step: 2 }); - equals( element.val(), "0", "value initialized to 0" ); + expect( 3 ); + var element = $( "#spin" ).val( 0 ).spinner({ step: 2 }); element.spinner( "stepUp" ); equals( element.val(), "2", "stepUp" ); @@ -107,16 +103,13 @@ test( "step, 2", function() { }); test( "step, 0.7", function() { - expect( 2 ); - var element = $("#spin").spinner({ + expect( 1 ); + var element = $("#spin").val( 0 ).spinner({ step: 0.7 }); - equals( element.val(), "0", "value initialized to 0" ); element.spinner( "stepUp" ); equals( element.val(), "0.7", "stepUp" ); }); -// TODO: test value - })( jQuery ); diff --git a/ui/jquery.ui.spinner.js b/ui/jquery.ui.spinner.js index ffcead73d..a5c25cd34 100644 --- a/ui/jquery.ui.spinner.js +++ b/ui/jquery.ui.spinner.js @@ -15,10 +15,10 @@ function modifier( fn ) { return function() { - var previous = this.options.value; + var previous = this.element.val(); fn.apply( this, arguments ); this._refresh(); - if ( previous !== this.options.value ) { + if ( previous !== this.element.val() ) { this._trigger( "change" ); } }; @@ -35,7 +35,6 @@ $.widget( "ui.spinner", { numberFormat: null, page: 10, step: 1, - value: 0, change: null, spin: null, @@ -44,7 +43,7 @@ $.widget( "ui.spinner", { }, _create: function() { - this._value( this.options.value ); + this._value( this.element.val(), true ); this._draw(); this._bind( this._events ); this._refresh(); @@ -54,7 +53,7 @@ $.widget( "ui.spinner", { var options = {}, element = this.element; - $.each( [ "min", "max", "step", "value" ], function( i, option ) { + $.each( [ "min", "max", "step" ], function( i, option ) { var value = element.attr( option ); if ( value !== undefined && value.length ) { options[ option ] = value; @@ -76,15 +75,8 @@ $.widget( "ui.spinner", { this.previous = this.element.val(); }, blur: function( event ) { - // don't clear invalid values on blur - var value = this.element.val(); - this._value( value ); - if ( this.element.val() === "" ) { - this.element.val( value ); - } + this._refresh(); this.uiSpinner.removeClass( "ui-state-active" ); - // TODO: what should trigger change? - // element.val() or options.value? if ( this.previous !== this.element.val() ) { this._trigger( "change", event ); } @@ -178,8 +170,6 @@ $.widget( "ui.spinner", { case keyCode.PAGE_DOWN: this._repeat( null, -options.page, event ); return true; - case keyCode.ENTER: - this._value( this.element.val() ); } return false; @@ -228,11 +218,11 @@ $.widget( "ui.spinner", { this.counter = 1; } - var newVal = this.value() + step * this._increment( this.counter ), + var value = this.value(), + newVal = value + step * this._increment( this.counter ), // fix precision from bad JS floating point math - precision = Math.max( this._precision( this.value() ), + precision = Math.max( this._precision( value ), this._precision( this.options.step ) ); - // clamp the new value newVal = this._trimValue( newVal.toFixed( precision ) ); @@ -281,10 +271,6 @@ $.widget( "ui.spinner", { }, _setOption: function( key, value ) { - if ( key === "value" ) { - return this._value( value ); - } - this._super( "_setOption", key, value ); if ( key === "disabled" ) { @@ -300,9 +286,7 @@ $.widget( "ui.spinner", { _setOptions: modifier(function( options ) { this._super( "_setOptions", options ); - - // handle any options that might cause value to change, e.g., min - this._value( this._trimValue( this.options.value ) ); + this._value( this.element.val() ); }), _parse: function( val ) { @@ -312,24 +296,37 @@ $.widget( "ui.spinner", { return isNaN( val ) ? null : val; }, - _format: function() { - var num = this.options.value; - return window.Globalize && this.options.numberFormat ? Globalize.format( num, this.options.numberFormat ) : num; + _format: function( value ) { + if ( value === "" ) { + return ""; + } + return window.Globalize && this.options.numberFormat ? + Globalize.format( value, this.options.numberFormat ) : + value; }, _refresh: function() { - this.element - .val( this._format() ) - .attr({ - "aria-valuemin": this.options.min, - "aria-valuemax": this.options.max, - "aria-valuenow": this.options.value - }); + this.element.attr({ + "aria-valuemin": this.options.min, + "aria-valuemax": this.options.max, + // TODO: what should we do with values that can't be parsed? + "aria-valuenow": this._parse( this.element.val() ) + }); }, // update the value without triggering change - _value: function( value ) { - this.options.value = this._trimValue( this._parse(value) ); + _value: function( value, ignoreRange ) { + var parsed; + if ( value !== "" ) { + parsed = this._parse( value ); + if ( parsed !== null ) { + if ( !ignoreRange ) { + parsed = this._trimValue( parsed ); + } + value = this._format( parsed ); + } + } + this.element.val( value ); this._refresh(); }, @@ -370,9 +367,9 @@ $.widget( "ui.spinner", { value: function( newVal ) { if ( !arguments.length ) { - return this.options.value; + return this._parse( this.element.val() ); } - this.option( "value", newVal ); + modifier( this._value ).call( this, newVal ); }, widget: function() {