PDA

View Full Version : [1.1.x] Ext.ux.form.Spinner



K0bo
19 Sep 2007, 6:24 AM
Been working on a spinner form field for ext.
Though I share it with you guys.

For now it has the number and date functionality.
Additional functionality can be added easily.

Functionality:
- Basic spinning behaviour
- Spinner has draggable divider to change values
- keyUp and keyDown support
- Scrollwheel support
- Alternate spinning when 'Shift' is pressed while spinning

Demo:
http://members.upc.nl/j.chim/ext/spinner/ext-spinner.html

Feel free to comment and suggest improvements! :)

---
v0.1.1
- added Time strategy
- Mousedown gets repeated.
- PageUp & PageDown binding to alternate spinning
---
v0.2
- refactored Ext.ux.form.Spinner.Strategy
- fixed gui bug in ie6 when used in ext-form

Ext.ux.form.Spinner for ExtJS 2.0:
http://extjs.com/forum/showthread.php?t=16352

J.C. Bize
19 Sep 2007, 7:01 AM
Looks great! My only 2 suggestions would be:

1) Continue incrementing/decrementing values if the mouse button is held down on the up/down arrow.
2) Make the PageUp and PageDown keys synonymous with Shift+up/down.

Thanks for your contribution! I'm sure to use this in my next project. Are you planning on posting it to the Ext Community Extensions (http://extjs.com/learn/Ext_Extensions) page?

Cheers,
JC

K0bo
19 Sep 2007, 7:01 AM
Update demo with 'Time' functionality

--

Nice suggestions, going to change it.

Once the Spinner fit enough, I'll post it on the Community Extensions page

mikegiddens
19 Sep 2007, 7:09 AM
Kobo,

Great Job. I played with the demo and think it is a very nice ux. I can't think of a place that I could use it but I amnot the 90/10 rule. Keep up the good work.

-Mike

Animal
19 Sep 2007, 7:14 AM
Very nice job!

Just three little enhancements...

The spinner buttons need to be ClickRepeaters. http://extjs.com/deploy/ext/docs/output/Ext.util.ClickRepeater.html

Also, NumberFields validate on keyup, so handleMouseWheel should use a DelayedTask to perform validation 500ms after the mousewheel stopped moving. http://extjs.com/deploy/ext/docs/output/Ext.util.DelayedTask.html

The same DelayedTask instance could be used to validate 500ms after the ClickRepeater spinner buttons were released.

K0bo
19 Sep 2007, 7:27 AM
@Animal

Thank for pointing out ClickRepeaters! I was on the hunt for it :)

Since the spinner is inherited from the triggerfield it has no validation functionality.
Is there a nice way to use the validation which is already present certain fields? (like numberfield)

steffenk
19 Sep 2007, 7:28 AM
very nice and very useful, thx for sharing it !

evant
19 Sep 2007, 7:29 AM
Very cool.

I added a small modification to allow you to hold down the trigger (using ClickRepeater).

I'll tidy up the code and post it later (if you haven't added it already).

Animal
19 Sep 2007, 7:31 AM
This handles repeating clicks, and validates 500ms after the trigger was released and 500ms after mousewheel was released:



Ext.namespace("Ext.ux.form");

Ext.ux.form.Spinner = function(config){
Ext.ux.form.Spinner.superclass.constructor.call(this, config);
this.addEvents({
'spinup' : true,
'clickdown' : true
});
}

Ext.extend(Ext.ux.form.Spinner, Ext.form.TriggerField, {
triggerClass : 'x-form-spinner-trigger',
splitterClass : 'x-form-spinner-splitter',
validateTask : new Ext.util.DelayedTask(),

strategy : undefined,

//private
onRender : function(ct, position){
Ext.ux.form.Spinner.superclass.onRender.call(this, ct, position);

this.splitter = this.wrap.createChild({tag:'div', cls:this.splitterClass, style:'width:13px; height:2px;'});
this.splitter.show().setRight( (Ext.isIE) ? 1 : 2 );
this.splitter.show().setTop(10);

this.proxy = this.trigger.createProxy('', false, true);
this.proxy.addClass("x-form-spinner-proxy");
this.proxy.hide();
this.dd = new Ext.dd.DDProxy(this.splitter.dom.id, "SpinnerDrag", {dragElId: this.proxy.id});

this.initSpinner();
},

//private
initTrigger : Ext.emptyFn,

//private
initSpinner : function(){
this.keyNav = new Ext.KeyNav(this.el, {
"up" : function(e){
this.onSpinUp();
},

"down" : function(e){
this.onSpinDown();
},

scope : this
});

this.repeater = new Ext.util.ClickRepeater(this.trigger.dom);
this.repeater.on("click", this.onTriggerClick, this, {preventDefault:true});
this.trigger.on("mouseover", this.onMouseOver, this, {preventDefault:true});
this.trigger.on("mouseout", this.onMouseOut, this, {preventDefault:true});
this.trigger.on("mousemove", this.onMouseMove, this, {preventDefault:true});
this.trigger.on("mousedown", this.onMouseDown, this, {preventDefault:true});
this.trigger.on("mouseup", this.onMouseUp, this, {preventDefault:true});
this.wrap.on("mousewheel", this.handleMouseWheel, this);

this.dd.setXConstraint(0, 0, 10)
this.dd.setYConstraint(1500, 1500, 10);
this.dd.endDrag = this.endDrag.createDelegate(this);
this.dd.startDrag = this.startDrag.createDelegate(this);
this.dd.onDrag = this.onDrag.createDelegate(this);

if(this.strategy == undefined){
this.strategy = new Ext.ux.form.Spinner.NumberStrategy();
}
},

//private
onMouseOver : function(){
if(this.disabled){
return;
}
var middle = this.getMiddle();
this.__tmphcls = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-overup' : 'x-form-spinner-overdown';
this.trigger.addClass(this.__tmphcls);
},

//private
onMouseOut : function(){
this.trigger.removeClass(this.__tmphcls);
},

//private
onMouseMove : function(){
if(this.disabled){
return;
}
var middle = this.getMiddle();
if( ((Ext.EventObject.getPageY() > middle) && this.__tmphcls == "x-form-spinner-overup") ||
((Ext.EventObject.getPageY() < middle) && this.__tmphcls == "x-form-spinner-overdown")){
}
},

//private
onMouseDown : function(){
if(this.disabled){
return;
}
var middle = this.getMiddle();
this.__tmpccls = (Ext.EventObject.getPageY() < middle) ? 'x-form-spinner-clickup' : 'x-form-spinner-clickdown';
this.trigger.addClass(this.__tmpccls);
},

//private
onMouseUp : function(){
this.trigger.removeClass(this.__tmpccls);
},

//private
onTriggerClick : function(){
if(this.disabled){
return;
}
var middle = this.getMiddle();
var ud = (Ext.EventObject.getPageY() < middle) ? 'Up' : 'Down';
this['onSpin'+ud]();
},

//private
getMiddle : function(){
var t = this.trigger.getTop();
var h = this.trigger.getHeight();
var middle = t + (h/2);
return middle;
},

handleMouseWheel : function(e){
var delta = e.getWheelDelta();
if(delta > 0){
this.onSpinUp();
e.stopEvent();
} else if(delta < 0){
this.onSpinDown();
e.stopEvent();
}
},

//private
startDrag : function(){
this.proxy.show();
this._previousY = Ext.fly(this.dd.getDragEl()).getTop();
},

//private
endDrag : function(){
this.proxy.hide();
},

//private
onDrag : function(){
if(this.disabled){
return;
}
var y = Ext.fly(this.dd.getDragEl()).getTop();
var ud = '';

if(this._previousY > y){ud = 'Up';} //up
if(this._previousY < y){ud = 'Down';} //down

if(ud != ''){
this['onSpin'+ud]();
}

this._previousY = y;
},

//private
onSpinDown : function(){
if(Ext.EventObject.shiftKey == true){
this.strategy.onSpinDownAlternate(this);
}else{
this.strategy.onSpinDown(this);
}
this.fireEvent("spindown", this);
this.validateTask.delay(this.validate, 500);
},

//private
onSpinUp : function(){
if(Ext.EventObject.shiftKey == true){
this.strategy.onSpinUpAlternate(this);
}else{
this.strategy.onSpinUp(this);
}
this.fireEvent("spinup", this);
this.validateTask.delay(this.validate, 500);
}

});

Animal
19 Sep 2007, 7:32 AM
You can specify a validate method, so

you could try poking Ext.form.NumberField.prototype.validate into the Spinner's validate property. Then you'd just need to set the various properties that NumberField's validator uses.

I'll try it here...

steffenk
19 Sep 2007, 7:32 AM
wow, animal, you're incredible fast!

Animal
19 Sep 2007, 7:40 AM
eg:



var s = new Ext.ux.form.Spinner({
validateValue: Ext.form.NumberField.prototype.validateValue,
parseValue: Ext.form.NumberField.prototype.parseValue,
format: Ext.form.NumberField.prototype.format,
minText: Ext.form.NumberField.prototype.minText,
maxText: Ext.form.NumberField.prototype.maxText,
nanText: Ext.form.NumberField.prototype.nanText,
minValue: 10,
maxValue: 50,
readOnly: true
});

Animal
19 Sep 2007, 7:43 AM
The validateTask DelayedTask isn't delaying.

It should only set the field to invalid after you stop spinning. I'll look into that.

Animal
19 Sep 2007, 7:56 AM
OK, it's the SpinnerStrategy calling setValue which performs validation immediately.

Probably the SpinnerStrategy should only change the DOM input element's raw value during change, and the DelayedTask should finally perform the setValue when they've quit either spinning or mousewheeling.

K0bo
19 Sep 2007, 7:58 AM
Implemented the clickrepeater for mousedown and bound pageup/down to alternate spinning

@Animal
Thanks for the headsup on validation.
I'll look into it.

Animal
19 Sep 2007, 11:46 PM
OK, what's needed for "delayed" validation is for SpinnerStrategy to use setRawValue to set the changed value on each increment. That sets the value without triggering immediate validation.

It's the SpinnerStrategy that must own the DelayedTask, and must fire off a delayed call to the Field's validate method after setting the raw value. The task will be cancelled when the next repeat click comes through in a few milliseconds. When they release the spinner button, the task's timer will expire, and the field will then validate.

K0bo
20 Sep 2007, 1:27 AM
I've refactored the Spinner.Strategy.
It's much cleaner and smaller (34%) :D

I added the init function. My idea is to set/copy the validation routines to the Spinner in the init function when a strategy hasn't been initialized yet (init on first spin).

I won't be able to look in this until weekend, so if someone wants to look into the validation part... Feel free to do so ;)



/***
* Abstract Strategy
*/
Ext.ux.form.Spinner.Strategy = function(config){
Ext.apply(this, config);
};

Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
inited : false, //protected

defaultValue : 0,
minValue : undefined,
maxValue : undefined,
incrementValue : 1,
alternateIncrementValue : 5,

init : function(field){
this.inited = true;
//extend

//set validation routines on field??
},

onSpinUp : function(field){
this.spin(field, false, false);
},

onSpinDown : function(field){
this.spin(field, true, false);
},

onSpinUpAlternate : function(field){
this.spin(field, false, true);
},

onSpinDownAlternate : function(field){
this.spin(field, true, true);
},

spin : function(field, down, alternate){
if(!this.inited){
this.init(field);
}
//extend
},

fixBoundries : function(value){
return value;
//overwrite
}
});

/***
* Concrete Strategy: Numbers
*/
Ext.ux.form.Spinner.NumberStrategy = function(config){
Ext.ux.form.Spinner.NumberStrategy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.ux.form.Spinner.NumberStrategy, Ext.ux.form.Spinner.Strategy, {

init : function(field){
Ext.ux.form.Spinner.NumberStrategy.superclass.init.call(this, field);

// Ext.form.NumberField.superclass.initEvents.call(field);
/*
field.allowDecimals = Ext.form.NumberField.prototype.allowDecimals;
field.decimalSeparator = Ext.form.NumberField.prototype.decimalSeparator;
field.decimalPrecision = Ext.form.NumberField.prototype.decimalPrecision;
field.allowNegative = Ext.form.NumberField.prototype.allowNegative;
field.minValue = this.minValue;
field.maxValue = this.maxValue;
field.minText = Ext.form.NumberField.prototype.minText;
field.maxText = Ext.form.NumberField.prototype.maxText;
field.nanText = Ext.form.NumberField.prototype.nanText;

field.validateValue = Ext.form.NumberField.prototype.validateValue;
field.getValue = Ext.form.NumberField.prototype.getValue;
field.parseValue = Ext.form.NumberField.prototype.parseValue;
field.fixPrecision = Ext.form.NumberField.prototype.fixPrecision;
field.setValue = Ext.form.NumberField.prototype.setValue;
field.decimalPrecisionFcn = Ext.form.NumberField.prototype.decimalPrecisionFcn;
field.beforeBlur = Ext.form.NumberField.prototype.beforeBlur;
*/
},

spin : function(field, down, alternate){
Ext.ux.form.Spinner.NumberStrategy.superclass.spin.call(this, field, down, alternate);

var v = parseFloat(field.getValue());
var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;

(down == true) ? v -= incr : v += incr ;
v = (isNaN(v)) ? this.defaultValue : v;
v = this.fixBoundries(v);
field.setRawValue(v);
},

fixBoundries : function(value){
var v = value;
if(this.minValue != undefined && v < this.minValue){
v = this.minValue;
}
if(this.maxValue != undefined && v > this.maxValue){
v = this.maxValue;
}
return v;
}
});


/***
* Concrete Strategy: Date
*/
Ext.ux.form.Spinner.DateStrategy = function(config){
Ext.ux.form.Spinner.DateStrategy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.ux.form.Spinner.DateStrategy, Ext.ux.form.Spinner.Strategy, {
defaultValue : new Date(),
format : "Y-m-d",
incrementValue : 1,
incrementConstant : Date.DAY,
alternateIncrementValue : 1,
alternateIncrementConstant : Date.MONTH,

spin : function(field, down, alternate){
Ext.ux.form.Spinner.DateStrategy.superclass.spin.call(this);

var v = field.getValue();
v = Date.parseDate(v, this.format);
var dir = (down == true) ? -1 : 1 ;
var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
var dtconst = (alternate == true) ? this.alternateIncrementConstant : this.incrementConstant;

if(typeof this.defaultValue == 'string'){
this.defaultValue = Date.parseDate(this.defaultValue, this.format);
}

v = (v) ? v.add(dtconst, dir*incr) : this.defaultValue;

v = this.fixBoundries(v);
field.setRawValue(v.format(this.format));
},

//private
fixBoundries : function(date){
var dt = date;
var min = (typeof this.minValue == 'string') ? Date.parseDate(this.minValue, this.format) : this.minValue ;
var max = (typeof this.maxValue == 'string') ? Date.parseDate(this.maxValue, this.format) : this.maxValue ;

if(this.minValue != undefined && dt < min){
dt = min;
}
if(this.maxValue != undefined && dt > max){
dt = max;
}

return dt;
}
});


/***
* Concrete Strategy: Time
*/
Ext.ux.form.Spinner.TimeStrategy = function(config){
Ext.ux.form.Spinner.TimeStrategy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.ux.form.Spinner.TimeStrategy, Ext.ux.form.Spinner.DateStrategy, {
format : "H:i",
incrementValue : 1,
incrementConstant : Date.MINUTE,
alternateIncrementValue : 1,
alternateIncrementConstant : Date.HOUR
});

Animal
20 Sep 2007, 2:21 AM
I think it just needs a tiny tweak. My additions in bold:



/***
* Abstract Strategy
*/
Ext.ux.form.Spinner.Strategy = function(config){
Ext.apply(this, config);
};

Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
inited : false, //protected

defaultValue : 0,
minValue : undefined,
maxValue : undefined,
incrementValue : 1,
alternateIncrementValue : 5,
validationTask: new Ext.util.DelayedTask();

init : function(field){
this.inited = true;
//extend

//set validation routines on field??
},

onSpinUp : function(field){
this.spin(field, false, false);
this.validationTask.delay(500, this.field.validate)
},

onSpinDown : function(field){
this.spin(field, true, false);
this.validationTask.delay(500, this.field.validate)
},

onSpinUpAlternate : function(field){
this.spin(field, false, true);
},

onSpinDownAlternate : function(field){
this.spin(field, true, true);
},

spin : function(field, down, alternate){
if(!this.inited){
this.init(field);
}
//extend
},

fixBoundries : function(value){
return value;
//overwrite
}
});

/***
* Concrete Strategy: Numbers
*/
Ext.ux.form.Spinner.NumberStrategy = function(config){
Ext.ux.form.Spinner.NumberStrategy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.ux.form.Spinner.NumberStrategy, Ext.ux.form.Spinner.Strategy, {

init : function(field){
Ext.ux.form.Spinner.NumberStrategy.superclass.init.call(this, field);

// Ext.form.NumberField.superclass.initEvents.call(field);
/*
field.allowDecimals = Ext.form.NumberField.prototype.allowDecimals;
field.decimalSeparator = Ext.form.NumberField.prototype.decimalSeparator;
field.decimalPrecision = Ext.form.NumberField.prototype.decimalPrecision;
field.allowNegative = Ext.form.NumberField.prototype.allowNegative;
field.minValue = this.minValue;
field.maxValue = this.maxValue;
field.minText = Ext.form.NumberField.prototype.minText;
field.maxText = Ext.form.NumberField.prototype.maxText;
field.nanText = Ext.form.NumberField.prototype.nanText;

field.validateValue = Ext.form.NumberField.prototype.validateValue;
field.getValue = Ext.form.NumberField.prototype.getValue;
field.parseValue = Ext.form.NumberField.prototype.parseValue;
field.fixPrecision = Ext.form.NumberField.prototype.fixPrecision;
field.setValue = Ext.form.NumberField.prototype.setValue;
field.decimalPrecisionFcn = Ext.form.NumberField.prototype.decimalPrecisionFcn;
field.beforeBlur = Ext.form.NumberField.prototype.beforeBlur;
*/
},

spin : function(field, down, alternate){
Ext.ux.form.Spinner.NumberStrategy.superclass.spin.call(this, field, down, alternate);

var v = parseFloat(field.getValue());
var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;

(down == true) ? v -= incr : v += incr ;
v = (isNaN(v)) ? this.defaultValue : v;
v = this.fixBoundries(v);
field.setRawValue(v);
},

fixBoundries : function(value){
var v = value;
if(this.minValue != undefined && v < this.minValue){
v = this.minValue;
}
if(this.maxValue != undefined && v > this.maxValue){
v = this.maxValue;
}
return v;
}
});


/***
* Concrete Strategy: Date
*/
Ext.ux.form.Spinner.DateStrategy = function(config){
Ext.ux.form.Spinner.DateStrategy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.ux.form.Spinner.DateStrategy, Ext.ux.form.Spinner.Strategy, {
defaultValue : new Date(),
format : "Y-m-d",
incrementValue : 1,
incrementConstant : Date.DAY,
alternateIncrementValue : 1,
alternateIncrementConstant : Date.MONTH,

spin : function(field, down, alternate){
Ext.ux.form.Spinner.DateStrategy.superclass.spin.call(this);

var v = field.getValue();
v = Date.parseDate(v, this.format);
var dir = (down == true) ? -1 : 1 ;
var incr = (alternate == true) ? this.alternateIncrementValue : this.incrementValue;
var dtconst = (alternate == true) ? this.alternateIncrementConstant : this.incrementConstant;

if(typeof this.defaultValue == 'string'){
this.defaultValue = Date.parseDate(this.defaultValue, this.format);
}

v = (v) ? v.add(dtconst, dir*incr) : this.defaultValue;

v = this.fixBoundries(v);
field.setRawValue(v.format(this.format));
},

//private
fixBoundries : function(date){
var dt = date;
var min = (typeof this.minValue == 'string') ? Date.parseDate(this.minValue, this.format) : this.minValue ;
var max = (typeof this.maxValue == 'string') ? Date.parseDate(this.maxValue, this.format) : this.maxValue ;

if(this.minValue != undefined && dt < min){
dt = min;
}
if(this.maxValue != undefined && dt > max){
dt = max;
}

return dt;
}
});


/***
* Concrete Strategy: Time
*/
Ext.ux.form.Spinner.TimeStrategy = function(config){
Ext.ux.form.Spinner.TimeStrategy.superclass.constructor.call(this, config);
};

Ext.extend(Ext.ux.form.Spinner.TimeStrategy, Ext.ux.form.Spinner.DateStrategy, {
format : "H:i",
incrementValue : 1,
incrementConstant : Date.MINUTE,
alternateIncrementValue : 1,
alternateIncrementConstant : Date.HOUR
});

Animal
20 Sep 2007, 2:24 AM
field.allowDecimals = Ext.form.NumberField.prototype.allowDecimals;
field.decimalSeparator = Ext.form.NumberField.prototype.decimalSeparator;
field.decimalPrecision = Ext.form.NumberField.prototype.decimalPrecision;
field.allowNegative = Ext.form.NumberField.prototype.allowNegative;
field.minValue = this.minValue;
field.maxValue = this.maxValue;
field.minText = Ext.form.NumberField.prototype.minText;
field.maxText = Ext.form.NumberField.prototype.maxText;
field.nanText = Ext.form.NumberField.prototype.nanText;

field.validateValue = Ext.form.NumberField.prototype.validateValue;
field.getValue = Ext.form.NumberField.prototype.getValue;
field.parseValue = Ext.form.NumberField.prototype.parseValue;
field.fixPrecision = Ext.form.NumberField.prototype.fixPrecision;
field.setValue = Ext.form.NumberField.prototype.setValue;
field.decimalPrecisionFcn = Ext.form.NumberField.prototype.decimalPrecisionFcn;
field.beforeBlur = Ext.form.NumberField.prototype.beforeBlur;


Use Ext.apply to copy functions into the fields prototype, and values into the field itself.

jon.whitcraft
20 Sep 2007, 4:09 AM
This is awesome!!!

Can you make sure you also post it on a wiki page

http://extjs.com/learn/Ext_Extensions

Thanks!!

skyey
20 Sep 2007, 6:06 PM
good job, i love you!

amon
26 Sep 2007, 4:50 AM
It's fine. I love it!

liero
26 Sep 2007, 5:07 AM
It could be good if the "Shift" key could be used with mousewheel as it works with down an up arrow (that is to say, secondary incrementing)

Thanks & very good job (I miss only slider and Ext will be perfect) !!!

K0bo
26 Sep 2007, 12:39 PM
@liero
I noticed the mousescroll+shift problem.
It is not working in firefox. Mousescroll+shift in IE6 works properly...
Still haven't figured out what causes the problem.

cutigersfan
28 Sep 2007, 5:21 AM
Has anyone put a label to the left of a spinner. I got it almost working, but the splitter isn't positioned correctly. I'm not a css expert, but it seems like a css issue.

K0bo
28 Sep 2007, 5:45 AM
I don't get that problem...
Just updated the demo with a dynamic form, with labels and spinners. And it's working properly.

Can you post the code you used?

-edit-
I just noticed the spinner within a form isn't working properly in IE6...

cutigersfan
29 Sep 2007, 4:26 AM
Well, I wasn't using the control as part of a formal ext form. It was more of a renegade control that changes items on the page display and is never submitted to a server. By doing it this way I created my own problem.

After looking at the HTML generated for your example I was not able to get the generated outer div to have the padding-left style. I'll have to dig into the ext code, but I now see it as the difference and if there is a way for ext to put that in there w/o the form.

I've never seen an example of a really creative form layout using ext controls. My project calls for a really different kind of form layout than the ext 2/3 column traditional one.

cutigersfan
1 Oct 2007, 8:55 AM
Any plans to port to 2.0?

K0bo
1 Oct 2007, 10:53 PM
I certainly will port it. I haven't looked into 2.0 yet...

mxracer
2 Oct 2007, 12:15 PM
Very nice. Any plans to allow decimal increments? Units of measurement that the user can toggle between?

K0bo
4 Oct 2007, 3:33 PM
It's already implemented, customizable and can be changed in runtime (while using it)
Just give the NumberStrategy the property: incrementValue with the increment you like.



var s = new Ext.ux.form.Spinner({
strategy: new Ext.ux.form.Spinner.NumberStrategy({incrementValue:.25, alternateIncrementValue:.50});
});
Same thing is applicable for the date/time strategy. You can configure them to increment in seconds or even years ;)

sagarshelke
15 Oct 2007, 11:50 PM
Hi,

Would this be upgraded to support ext 2.0?

Thanks,

Sagar

tof
16 Oct 2007, 2:26 AM
Very useful component :)

K0bo
22 Oct 2007, 6:04 AM
Just posted a new version with minor improvements.

@sagarshelke
Haven't dug into ext2.0 yet.
I'm kinda busy with other stuff right now.
But when I have time I'll certainly upgrade it to ext2.0 ;)

madrabaz
23 Oct 2007, 1:44 AM
Greate work;
for me this is the most useful extension after Sakalos's FileTree extension;
but unfortunately both of them does not support Ext 2.0 :(

Shmoo
25 Oct 2007, 10:06 PM
Great work Kobo! I'll be sure to use this in one my projects soon. I will give proper credits don't worry. I'll try and play with it when I have time.. I'm still swamped.. with other stuff... >.<

K0bo
26 Oct 2007, 4:14 AM
Upgraded it to extjs 2.0 ;)

http://extjs.com/forum/showthread.php?t=16352

mdm-adph
21 Nov 2007, 9:35 AM
Strange problem with the 1.1.1 version of this extension -- like a previous poster, i was having a problem with the spinner fields sometimes overlapping their labels and being misaligned whilst in a Ext.form.Form (when used in Internet Explorer), but then I changed the accompanying CSS file like so...

From:


.x-form-element .x-form-field-wrap { /* ie6 fix within ext-form */
position: relative !important;
position: absolute; /* ie6 */
}To...


.x-form-element .x-form-field-wrap { /* ie6 fix within ext-form */
position: relative !important;
}Uh... any idea why? I'm just glad it works, now, though. (Always worked fine in Firefox.)

Air_Mike
22 Dec 2007, 11:11 AM
Hello,

first of all I must say that this is a great extension...

...now, I'm using Ext 1.1.1 version and I have one problem in Firefox (imagine that this is
not happening in IE :))...
...when I press shift for alter spinning and click on spinning buttons after few clicks (usually tree) spinn buttons disappear... this is not the case when I click VERY slow on buttons...

Is it suppose to do that or what? ...how can I change or fix that?

Thank You...

K0bo
25 Dec 2007, 3:20 PM
Sounds like you are using Adblock in Firefox.
Shift + dubbelclick with adblock removes the 'clicked' element from the page.

I am suspecting that's your 'problem' :)

Either disable 'adblock', otherwise try dragging the 'divider' up and down to change values... ;)

Air_Mike
28 Dec 2007, 3:23 AM
Thank You,

it's exactly like you said it :">