PDA

View Full Version : [2.0] Ext.ux.form.Spinner



K0bo
26 Oct 2007, 4:12 AM
Presenting the spinner control for extjs 2.0.

Made some small changes on the 1.1.x version (http://extjs.com/forum/showthread.php?t=13244) to make it work with ExtJS 2.0
Make sure to remove the Spinner from ExtJS v1.1 as it conflicts with the one for ExtJS v2.0

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

Usage:

Create a new Spinner control with number spinning as default:

var spinner = new Ext.ux.form.Spinner();
spinner.applyToMarkup('existingInputText');New spinner. Initial value 10; Set it to a number spinner with min- and max value and custom increments.
var spinner = new Ext.ux.form.Spinner({
value: 10,
strategy: new Ext.ux.form.Spinner.NumberStrategy({minValue:0, maxValue:100, incrementValue:5, alternateIncrementValue:10})
});
spinner.applyToMarkup('existingInputText');New spinner. Set spinner to a time spinner.

var spinner = new Ext.ux.form.Spinner({
strategy: new Ext.ux.form.Spinner.TimeStrategy()
});
spinner.applyToMarkup('existingInputText');
New spinner. Set spinner to a date spinner with custom date format.
See this page (http://extjs.com/deploy/dev/docs/output/Date.html) for more formats. Applies to TimeSpinner too.

var spinner = new Ext.ux.form.Spinner({
strategy: new Ext.ux.form.Spinner.DateStrategy({format:'Y-m-d'})
});
spinner.applyToMarkup('existingInputText');
As of version 0.3 it's possible to pass strategy config in constructor. See post. (http://extjs.com/forum/showthread.php?p=121850#post121850)
supported 'xtype': [number, date, time]

var spinner = new Ext.ux.form.Spinner({
strategy:{
xtype:'number'
,minValue:0
,maxValue:100
}
,name:'mySpinner'
// ...
}); Updates:
-- 2008-08-27 (v0.35) --
[changed] - disable scrolling when field is not focused, preventing accidental scrolling
[added] - validation-call after spinning, with small delay (buffered)
[fixed] - double spinning bug. thanks vtswingkid! [post (http://extjs.com/forum/showthread.php?p=212124#post212124)]
[fixed] - spinner still working when disabled
[added] - generic spin event, for spinning up and down

-- 2008-05-08 (v0.3) --
[added] - new event 'spin', which fires after spinning up or down
[fixed] - prevent pagescroll upon pageup/down event in Opera
[fixed] - invalid date/time formatting. patch by almostchristian's. [post (http://extjs.com/forum/showthread.php?p=120590#post120590)]
[added] - jsakalos patch, enabling passing strategy config in constructor. [post (http://extjs.com/forum/showthread.php?p=121850#post121850)]
[fixed] - Spinning while Spinner is set to readOnly or disabled
[added] - Releasing plugin under BSD-license

-- 2008-01-10 (v0.21) --
[fixed] - Minor changes to SpinnerStrategy.js to make it work with the SpinnerPlugin (http://extjs.com/forum/showthread.php?t=22663)

-- 2008-01-04 (v0.2) --
[fixed] - spinning twice onclick
[added] - registered xtype: "uxspinner"
[added] - precision attributes for numberstrategy (allowDecimals & decimalPrecision)

Ideas
- smartspin option for number- and date strategy

galdaka
26 Oct 2007, 4:14 AM
Excellent work!!

Thanks for share,

Grimsk
26 Oct 2007, 6:22 AM
Well Done

brian.moeskau
26 Oct 2007, 1:18 PM
It would be really cool if you could show an example using TwinTriggerField (it's an undocumented example, but for fields that also have a natural selection mechanism like date and time it seems like it would be really useful -- see http://extjs.com/deploy/dev/examples/form/custom.html). That way you can use the picker to move in large leaps, or the spinner to move in small increments.

EDIT: The TwinTriggerField class iteself is in the TriggerField.js file at the bottom.

Animal
26 Oct 2007, 1:42 PM
TriggerField already sets up a click listener on the trigger to call onTriggerClick. That's where the extra event is coming from.

ClickRepeater only fires click events during the time the mouse is down. A down and then an up will fire the TriggerField's native click handler. You'll have to remove that first.

cybershield
31 Oct 2007, 12:28 PM
I haven't test it thoroughly, so far everything works fine, except for clicking up and down. It will fire the spinning twice... on mousedown and mouseup
My guess so far is that it has something to do with the ClickRepeater...
Does anyone have an solution for the problem?


Add


this.trigger.un("click", this.onTriggerClick);

before


this.repeater = new Ext.util.ClickRepeater(this.trigger.dom);
this.repeater.on("click", this.onTriggerClick, this, {preventDefault:true});


The spinner control don't validate the value when click the arrow, you can add into mouseup event the validate check:



onMouseUp : function() {
this.trigger.removeClass(this.__tmpccls);
this.validate(); // check value
},


Good work K0bo ;)

Ciao

jo2008
5 Nov 2007, 1:44 AM
I applied the last fix and the clicks on the arrows work now. But another problem has been created through this:

If you click in the spinner textfield so that the cursor appears and then click on the down arrow, the value is increased instead of decreased.

In the original version before the twin trigger thing, this effect was reversed by the second event.

Maybe we have to use the other event to prevent this from happening.

dafimoto
5 Nov 2007, 2:23 AM
I've noticed that when using firefox 2.0 and putting spinner into a small column width 65px with spinner's width of 55px it will show up a horizontal scrollbar on bottom.

After examining this issue with firebug i've noticed a left:79px statement in the generated style for the proxy element.
This was probably because the splitter was set to the right using setRight ....

the correction i've made was:


this.proxy.setStyle('left','0px');


and the scrollbar was gone.

Best regards,
Bogdan

cutigersfan
7 Nov 2007, 6:58 AM
I've put spinners in several panels of an accordian layout. The panel that displays openly by default has all spinners looking fine. However the ones that are closed by default have the splitter image placed to the left of the textbox.

It appears that it's due to the wrap with being set to 0. It doesn't matter if a width is specified or not.

Anyone else tried this?

mdissel
7 Nov 2007, 11:45 AM
Thanks for sharing, when i do a single click on the button the number is de/incremented with 2. Is that correct?

J.C. Bize
7 Nov 2007, 12:22 PM
Thanks for sharing, when i do a single click on the button the number is de/incremented with 2. Is that correct?

It looks like it gets incremented once on mousedown, and then once again on mouseup... probably not the intended behavior.

Cheers,
JC

K0bo
7 Nov 2007, 1:20 PM
The faulty increment when you click on the spinner is a bug.

I haven't resolved it yet, because I'm busy with other stuff.
The solution presented by cyberfield seems to fix the problem, but introduces a new problem according to jo2008. I haven't looked into fix and new problem yet.

cybershield
9 Nov 2007, 1:46 PM
The solution presented by cyberfield seems to fix the problem, but introduces a new problem according to jo2008.

Sorry but my fix don't introduce this new problem, but already present also without my fix.

The problem is when onTriggerClick is called: Ext.EventObject.getPageY() is equal at 0 if the focus is over one textfield (also different textfield of spinner).
I don't understand why Ext.EventObject.getPageY() == 0.
If i set a breakpoint con firebug into onTriggerClick, Ext.EventObject.getPageY() is correct.
If i use console.log(Ext.EventObject.getPageY()), the console show 0 the first call. :-?

K0bo
10 Nov 2007, 1:24 PM
@cyberfield

Your fix does not introduce that 'new' problem. It seems to be present in the 1.1 version too...

I took a quick look on the spindown problem after focusing on the spinner and I came to the same conclusion as cyberfield.
I also get Ext.EventObject.getPageY() == 0.
Worth mentioning too is that the first call refers to the textfield and not the trigger image...

cybershield
11 Nov 2007, 6:29 AM
Is a bug of ExtJS ? :-?

blutarsky
15 Nov 2007, 1:49 AM
Hi everybody,

very good job K0bo, thank you very much!!!

I have a problem with this values:
new Ext.ux.form.Spinner({
strategy: new Ext.ux.form.Spinner.NumberStrategy({
minValue: 0,
maxValue: 100,
incrementValue: 0.1
})
Example:
up sequence:
0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999

down sequence:
0.7999999999999999
0.7
0.6
0.5
0.4
0.30000000000000004
0.20000000000000004
0.10000000000000003
2.7755575615628914e-17
0

blutarsky
15 Nov 2007, 3:10 AM
A possible solution is this (maybe):

SpinnerStrategy.js:

...
field.setRawValue(v.toFixed(2));
...
or add a new param 'fixedValue'
field.setRawValue(v.toFixed(fixedValue));

eclucas
21 Nov 2007, 9:51 AM
hi all, i have a spinner control but his images don

vtswingkid
5 Dec 2007, 12:44 PM
Nice component...

I added a couple things:

* triggerstate counter to eliminate the double step
* editable boolean flag
* registered it so it has an xtype

seems to be working well.

fionn
13 Dec 2007, 9:33 AM
@vtswingkid: nice package and it seems to work well.
However when I put it into a FormPanel of my own the spinner-split.gif appears left of the input field instead of right between the arrows.... Looks like sort of a "-" Prefix. Any idea what could cause this?

Edit/Update: in Firefox the gif appears left of the input field. In IE it appears inside the input field, left of the spinner box.

fionn
14 Dec 2007, 6:56 AM
I've put spinners in several panels of an accordian layout. The panel that displays openly by default has all spinners looking fine. However the ones that are closed by default have the splitter image placed to the left of the textbox.

It appears that it's due to the wrap with being set to 0. It doesn't matter if a width is specified or not.

Anyone else tried this?

I think this is exactly what I wrote in my previous post. It looks about right when you set the wrap width to (<spinner_width>+17px). Where would be the right place to put this?

prophet
26 Dec 2007, 9:11 AM
How can I make this into a valid xtype for building FormPanels?

prophet
26 Dec 2007, 9:17 AM
Answered my own question.
Add this to the end of the code:

Ext.reg('uxspinner',Ext.ux.form.Spinner);


How can I make this into a valid xtype for building FormPanels?

K0bo
4 Jan 2008, 10:22 AM
I updated the spinner widget.
[fixed] spinning twice onclick
[added] registered xtype: "uxspinner"
[added] numberstrategy precision attributes {allowDecimals & decimalPrecision}Thanks everyone for helping out.

Please leave a reply if the splitter-position problem still persists.

I had an idea for a smartspin option for the date and time:
The spinner spins the day or (month/year/hour/minute/second) depending where your caret/cursor is positioned in the field...

If there is enough interest in it, I'll look into it.
(btw: Are caret functions already present in the ext framework? Because I couldn't find it. Maybe it's a nice feature in the next ext update :) )

K0bo
9 Jan 2008, 6:49 PM
Nice component...

I added a couple things:

* triggerstate counter to eliminate the double step
* editable boolean flag
* registered it so it has an xtype

seems to be working well.

The "editable boolean flag" is unnecessary, since you can use the native property: "readOnly"
To disabled you can use the property "disabled".

fionn
14 Jan 2008, 4:26 AM
Please leave a reply if the splitter-position problem still persists.



Yes, the problem still persists, unfortunately!

kind regards,
Fionn

K0bo
14 Jan 2008, 3:30 PM
Can you post your source? (To replicate the problem)

blutarsky
23 Jan 2008, 3:19 AM
If you click in the spinner textfield so that the cursor appears and then click on the down arrow, the value is increased instead of decreased.



Hi,

I try the new version spinner2_v0_21, and I found again the bug linked above.

But the problem had been resolved in the spinner2_v0_1_2

temporary
25 Jan 2008, 6:09 AM
Can someone explain me what the splitter does? Or should do?
It's located left to the Spinner-Textfield, I saw in the code that it creates a DDProxy, but whatever I do with it, nothing happens?

fionn
28 Jan 2008, 8:31 AM
Can someone explain me what the splitter does? Or should do?

It should be right to the input field (but is not always so). I think the original idea was that you can grab it with the mouse and drag it up or downwards to increase or decrease the contents of the input field accordingly.

temporary
28 Jan 2008, 11:00 AM
It should be right to the input field (but is not always so). I think the original idea was that you can grab it with the mouse and drag it up or downwards to increase or decrease the contents of the input field accordingly.

Hmm strange. It's definitely left of the input field here. Will have a look at the CSS, but nevertheless the drag should work, which it doesn't ;-)

Stephan

K0bo
28 Jan 2008, 3:57 PM
Hmm strange. It's definitely left of the input field here. Will have a look at the CSS, but nevertheless the drag should work, which it doesn't ;-)

Stephan

Can you provide system/browser specs with a code sample of the problem? (splitter on left side)

As you said, the splitter should be on the right side of the control and when you drag it, the spinner should count up or down, depending on the drag direction...

almostchristian
6 Feb 2008, 6:32 PM
I was having issues with using timestrategy in version 0.21 using ExtJs 2.01 and found a solution. The problem involved the spinner giving an invalid value which I believe is caused by a problem in formatting. I don't know how you got it working in your sample but this is the code that caused the problem and the fix:

Replace this code found in Ext.ux.form.Spinner.DateStrategy.spin()

field.setRawValue(v.format(this.format));with

field.setRawValue(Ext.util.Format.date(v,this.format));I hope this helps and thanks for the great work!

dawesi
6 Feb 2008, 6:58 PM
super sweet extension...

with the smart spinner and dates, when you hold shift it changes the month, how do I spin the year? (cntl-shift click was my first thought... but no dice)

jsakalos
9 Feb 2008, 6:27 PM
Hi k0bo,

I recommend to add the following block of code to the Spinner initSpinner function just before creating the default number strategy by the end of the function:



if('object' == typeof this.strategy && this.strategy.xtype) {
switch(this.strategy.xtype) {
case 'number':
this.strategy = new Ext.ux.form.Spinner.NumberStrategy(this.strategy);

// achieve a part of NumberField functionality
this.validateValue = Ext.form.NumberField.prototype.validateValue;
this.minText = Ext.form.NumberField.prototype.minText;
this.maxText = Ext.form.NumberField.prototype.maxText;
this.nanText = Ext.form.NumberField.prototype.nanText;
this.getValue = Ext.form.NumberField.prototype.getValue;
this.setValue = Ext.form.NumberField.prototype.setValue;
this.parseValue = Ext.form.NumberField.prototype.parseValue;
this.fixPrecision = Ext.form.NumberField.prototype.fixPrecision;
break;

case 'date':
this.strategy = new Ext.ux.form.Spinner.DateStrategy(this.strategy);
break;

case 'time':
this.strategy = new Ext.ux.form.Spinner.TimeStrategy(this.strategy);
break;

default:
delete(this.strategy);
break;
}
delete(this.strategy.xtype);
}
if(this.strategy == undefined){ // existing line

This way it will be possible to pass strategy config in constructor like this:



var spinner = new Ext.ux.form.Spinner({
strategy:{
xtype:'number'
,minValue:0
,maxValue:100
}
,name:'mySpinner'
// ...
});
This was quite important for me because I deliver field configurations from server JSON encoded where I can deliver object but I cannot deliver instantiated Spinner.Strategy. Also, I needed to achieve NumberField functionality as close as possible so I included some methods from NumberField prototype.

What would be the best for me would be a plugin that would also add the spinner trigger - I know you have plugin that add spinning functionality. The original field type would be preserved in this case, including validation methods and texts, masking regular expressions, etc. and the trigger and spinning functionality would be added.

Do you think about creating such plugin?

Cheers,

joaquinfq
20 Feb 2008, 11:12 PM
I have problem with Spinner2 0.21

I opened ext-spinner.html for testing this extension with konqueror but if i clic in spinner, only decrement... i can't increment the value of spinner.. only down arrow is pressed although i clic in up arrow.

I am using Ext 2.0.1.

mcp
9 Mar 2008, 7:31 AM
Hi k0bo,

I recommend to add the following block of code to the Spinner initSpinner function just before creating the default number strategy by the end of the function:



...
This way it will be possible to pass strategy config in constructor like this:



var spinner = new Ext.ux.form.Spinner({
strategy:{
xtype:'number'
,minValue:0
,maxValue:100
}
,name:'mySpinner'
// ...
});
This was quite important for me because I deliver field configurations from server JSON encoded where I can deliver object but I cannot deliver instantiated Spinner.Strategy. Also, I needed to achieve NumberField functionality as close as possible so I included some methods from NumberField prototype.


YES!!, thank you so much again, Saki!

Chris in Cambridge
18 Apr 2008, 10:48 AM
Hi K0bo,

Thanks very much for the spinner widget. Very nice!

I could not find any license information on your spinner widget. What license is it released under? I am interested in using in a non-LPGL project.

Thanks!

nassaja-rus
21 Apr 2008, 8:51 AM
Spinner button is on left side of field, over field value, and i cant see value. This is bug?

nassaja-rus
21 Apr 2008, 10:27 PM
Sorry, all fine. i'm forgot unload old extension for 1.x

yazan_rababa
7 May 2008, 1:53 PM
hi guys ,

really very good

but i have question plz

how can do increment like this

1.01
1.02
1.03
.
.
.


thanks alot
regards

yazan_rababa
8 May 2008, 12:36 AM
hi again guys ,

im using Spinner , i dont know why when i try to hide the item
it dose not work very well , coz the lable does not hide


var item= new Ext.ux.form.Spinner({
fieldLabel: 'Deviation',
hidden : true,
name: 'deviation',
strategy: new Ext.ux.form.Spinner.NumberStrategy({minValue:'0', maxValue:'130',incrementValue: 0.1})
});


thanks

K0bo
8 May 2008, 10:30 AM
@Chris in Cambridge (http://extjs.com/forum/member.php?u=5803)
For future versions of the Spinner I'll be releasing it under BSD-license.

@yazan_rababa (http://extjs.com/forum/member.php?u=32686)
As for the "hide" option, I'm getting the same behaviour with a regular textfield. So I'm guessing it's an ExtJS thing.
Checkout Animal's posting (http://extjs.com/forum/showthread.php?p=166255#post166255), sounds like you're experiencing this problem.

Version 0.3 released ;)

ray007
21 May 2008, 1:04 AM
what would be cool is to have the spinner (optionally) round the value to a multiple of the spinning-tick on spinUp and spinDown.

ray007
11 Jun 2008, 5:06 AM
I think it would also be good if the SpinnerStrategies used the values (minValues, maxValue, ...) that are set on the field and didn't require to transfer the config into the strategy too.

A first step towards that goal could be like this:


/***
* Abstract Strategy
* URL: http://extjs.com/forum/showthread.php?t=16352
*/
Ext.ux.form.Spinner.Strategy = function(config){
Ext.apply(this, config);
};

Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
defaultValue : 0,
minValue : undefined,
maxValue : undefined,
incrementValue : 1,
alternateIncrementValue : 5,

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){
//extend
},

fixBoundries : function(value, field) {
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, {

allowDecimals : true,
decimalPrecision : 2,

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);
field.setRawValue(v);
},

fixBoundries : function(value, field) {
var v = value;

if(field.minValue != undefined && v < field.minValue){
v = field.minValue;
}
if(field.maxValue != undefined && v > field.maxValue){
v = field.maxValue;
}

return this.fixPrecision(v, field);
},

// private
fixPrecision : function(value, field) {
var nan = isNaN(value);
if(!field.allowDecimals || field.decimalPrecision == -1 || nan || !value){
return nan ? '' : value;
}
return parseFloat(parseFloat(value).toFixed(field.decimalPrecision));
}
});


/***
* 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.getRawValue();

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);
field.setRawValue(Ext.util.Format.date(v,this.format));
},

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

if(field.minValue != undefined && dt < min){
dt = min;
}
if(field.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
});
And the strategies maybe could use an init-function that's called with the field as parameter ... ?

K0bo
11 Jun 2008, 5:46 AM
@Ray

I specifically designed the SpinnerStrategy so the minValue and maxValue are optional. So you can make, for example an ArrayStrategy, DatasetStrategy or ColourStrategy. Which don't require the minValue and maxValue option...

Of course you're free to modify the code for your own use ;)

mephi
13 Jun 2008, 12:13 AM
Hi guys, I have a problem ...

First of all I want to say that I`m new to ext-js :P

I work on a symfony project, and I need to include this spinner plugin.

I really don't know where to add the images/css/js files so that the plugin will work on one of my modules.

Most of the project is made with ext-js but I havent used any new plugins, just the base components of ext-js.

If u show me a link or a FAQ of how to include plugins files(images/css/js) into bigger projects I would appreciate.

ray007
13 Jun 2008, 12:42 AM
@Ray

I specifically designed the SpinnerStrategy so the minValue and maxValue are optional. So you can make, for example an ArrayStrategy, DatasetStrategy or ColourStrategy. Which don't require the minValue and maxValue option...


And it's good that min and max are optional. But in the cases where they are wanted, one place (i.e. the field) should be enough to have them, and the fields that already have them also already use them for things like validation ...

rizjoj
13 Jun 2008, 7:56 PM
Hi,

If you have a tab panel and place spinner fields on either the header or footer of a grid panel in each tab, the spinner on the tab that is not active on rendering has its splitter bar misaligned.

In the code below both spinner fields have been configured with width: 40px.


Ext.namespace('myApp');

Ext.onReady(function(){

// Dummy data for both grids
var gridData = [
['Row One'],
['Row Two']
];

// Grid 1: Data Store
var store1 = new Ext.data.SimpleStore({
fields: [{name: 'field1'}]
});

// Grid 1: GridPanel
myApp.grid1 = new Ext.grid.GridPanel({
store: store1,
border: true,
height: 150,
columns: [{id:'field1',header: "Header 1", width: 160, dataIndex: 'field1'}],
bbar: [
'Use the spinner to select &nbsp;',
{
xtype: 'uxspinner',
width: 40, /* ** Width 40 for this spinner as well ** */
strategy: {
xtype: 'number',
minValue: 0,
maxValue: 10
}
},
'&nbsp;out of 10.'
]
});

// Grid 1: Populate
store1.loadData(gridData);

// Grid 2: Data Store
var store2 = new Ext.data.SimpleStore({
fields: [{name: 'field2'}]
});

// Grid 2: GridPanel
myApp.grid2 = new Ext.grid.GridPanel({
store: store2,
border: true,
height: 150,
columns: [{id:'field2',header: "Header 2", width: 160, dataIndex: 'field2'}],
bbar: [
'Use this other spinner &nbsp;',
{
xtype: 'uxspinner',
width: 40, /* ** Width 40 for this spinner as well ** */
strategy: {
xtype: 'number',
minValue: 0,
maxValue: 20
}
},
'&nbsp;out of 20.' /* ** This gets hidden behind the spinner ** */
]
});

// Grid 2: Populate
store2.loadData(gridData);

// TabPanel: Two tabs which consist of Grid1 and Grid2 on each tab.
//1st tab is active on render. If you switch to 'activeTab:1', the spinner on tab 2
// renders ok but the splitbar of the spinner field on tab 1 is now misaligned.
myApp.tabpanel= new Ext.TabPanel({
activeTab: 0,
deferredRender: false,
layoutOnTabChange: true, // Doesn't change anything. Suggestion from one of the forum posts
hideLabel: true, // Doesn't change anything. Suggestion from one of the forum posts
autoTabs: true,
bodyBorder: false,
items: [{
title: 'Tab 1',
items: [myApp.grid1]
},{
title: 'Tab 2',
items: [myApp.grid2]
}]
});

// Viewport which houses the TabPanel
var viewport = new Ext.Viewport({
items:[{
region: 'center',
title: 'Center Region',
items: [{
xtype: 'panel',
title: 'Tab Panel',
items: [myApp.tabpanel]
}]
}]
});

});
The issue seems to be in the style attribute. On inspecting both spinner field elements in Firebug the differences seen are:

Spinner Field DOM in Grid 1 (which is on Tab1 and rendered/active on load)

<div id="ext-gen42" class="x-form-field-wrap" style="width: 40px;">
<input id="ext-comp-1013" class="x-form-text x-form-field" type="text" name="ext-comp-1013" autocomplete="off" size="16" style="width: 23px;"/>
<img id="ext-gen43" class="x-form-trigger x-form-spinner-trigger x-unselectable" src="http://extjs.com/s.gif" style="-moz-user-select: none;"/>
<div id="ext-gen48" class="x-form-spinner-splitter" style="width: 13px; height: 2px; visibility: visible; right: 2px; top: 10px;">
<div id="ext-gen49" class="x-form-spinner-proxy" style="width: 14px; height: 1px; position: relative; left: 0px; top: -10px; visibility: hidden;"/>
</div>
</div>Spinner Field DOM in Grid 2 (which is on Tab2 and hidden on load)

<div id="ext-gen112" class="x-form-field-wrap" style="width: 0px;">
<input id="ext-comp-1016" class="x-form-text x-form-field" type="text" name="ext-comp-1016" autocomplete="off" size="16" style="width: 40px;"/>
<img id="ext-gen113" class="x-form-trigger x-form-spinner-trigger x-unselectable" src="http://extjs.com/s.gif" style="-moz-user-select: none;"/>
<div id="ext-gen118" class="x-form-spinner-splitter" style="width: 13px; height: 2px; visibility: visible; right: 2px; top: 10px;">
<div id="ext-gen119" class="x-form-spinner-proxy" style="width: 14px; height: 1px; position: relative; left: 0px; top: 0px; visibility: hidden;"/>
</div>
</div>I've been attacking this problem for 2 days now without much luck. It seems to me that the hidden nature of the inactive panel is overriding the style of the second spinner field to width: 0 and my approach is to prevent this overriding. This also misaligns any text/components in the header/footer after the spinner field.

If I figure it out, I'll update this post. In the meantime, if anybody could help, provide suggestions or pointers, it would be much appreciated.

K0bo
14 Jun 2008, 6:32 AM
@rizjoj
After a quick look I couldn't locate the problem, but I did found out when you replace 'uxspinner' with 'datefield', the " out of 20" text in the second tab gets hidden behind the datefield too. The 'timefield' and 'combo' show the same problem.

I have a hunch that the problem may lie in 'triggerfield'; all form controls derived from 'triggerfield' show the same problem...

rizjoj
14 Jun 2008, 6:37 AM
Thanks K0bo, the fact that it may be the TriggerField as well did cross my mind. I'll see if I can find anything from the TriggerField source.

rizjoj
14 Jun 2008, 5:27 PM
K0bo,

From this link, http://extjs.com/forum/showthread.php?t=17242&page=2, its obvious that there is nothing wrong with the spinner control. It initializes when the tab renders and since the tabs are lazy rendered, the dimensions of the tab (its parent control) are probably zero somewhere.

But it does work if you add the tab on the fly AND show it:

tabpanel.add.apply(tabpanel,[tabconfig]);
tabconfig is the config object for the tabpanel with contains uxspinner in the tab's bbar.

However I still need to see if it works on the onRender event otherwise all those panels will have to be loaded regardless of whether the user views them or not (uses up memory)

Riz.

rizjoj
14 Jun 2008, 6:00 PM
This works. Notice the spinner in tab2 is rendered correctly (I didn't need to use the onRender listener). I've added a button that adds tabs on the fly with the spinner control as well.


Ext.namespace('myApp');

Ext.onReady(function(){

myApp.i = 2;

// Dummy data for both grids
var gridData = [
['Row One'],
['Row Two']
];

// Grid 1: Data Store
var store1 = new Ext.data.SimpleStore({
fields: [{name: 'field1'}]
});

// Grid 1: GridPanel
myApp.grid1 = new Ext.grid.GridPanel({
store: store1,
border: true,
height: 150,
columns: [{id:'field1',header: "Header 1", width: 160, dataIndex: 'field1'}],
bbar: [
'Use the spinner to select &nbsp;',
{
xtype: 'uxspinner',
width: 40,
strategy: {
xtype: 'number',
minValue: 0,
maxValue: 10
}
},
'&nbsp;out of 10.'
]
});

// Grid 1: Populate
store1.loadData(gridData);


// Grid 2: Data Store
var store2 = new Ext.data.SimpleStore({
fields: [{name: 'field2'}]
});

// Grid 2's toolbar
myApp.bbar2 = new Ext.Toolbar([
'Use this other spinner &nbsp;',
{
xtype: 'uxspinner',
width: 40,
strategy: {
xtype: 'number',
minValue: 0,
maxValue: 20
}
},
'&nbsp;out of 20.'
]);

// Grid 2: GridPanel
myApp.grid2 = new Ext.grid.GridPanel({
store: store1,
border: true,
height: 150,
columns: [{id:'field1',header: "Header 1", width: 160, dataIndex: 'field1'}],
bbar: [
'Use this other spinner &nbsp;',
{
xtype: 'uxspinner',
width: 40,
strategy: {
xtype: 'number',
minValue: 0,
maxValue: 20
}
},
'&nbsp;out of 20.'
]
});

// Grid 2: Populate
store2.loadData(gridData);

myApp.tabpanel= new Ext.TabPanel({
activeTab: 0,
layoutOnTabChange: true,
hideLabel: true,
autoTabs: true,
items: [{
title: 'Tab 1',
items: [myApp.grid1]
},{
title: 'Tab 2',
items: [myApp.grid2]
}]
});

// Tab configure template for tabs rendered on button click
// Exactly the same as the others.
var tabconfig = {
items: [{
xtype: 'grid',
store: store1,
border: true,
height: 150,
columns: [{id:'field1',header: "Header 1", width: 160, dataIndex: 'field1'}],
bbar: [
'Use this other spinner &nbsp;',
{
xtype: 'uxspinner',
width: 40,
strategy: {
xtype: 'number',
minValue: 0,
maxValue: 20
}
},
'&nbsp;out of 20.'
],
}]
}

var viewport = new Ext.Viewport({
items:[{
region: 'center',
title: 'Center Region',
items: [{
xtype: 'panel',
title: 'Tab Panel',
items: [myApp.tabpanel]
}],
buttons: [{
text: 'Add',
handler: function() {
// Adds a new tabs and sets its title.
// Uses the tabconfig object to create the componenets within
myApp.tabpanel.add.apply(myApp.tabpanel,[tabconfig]).setTitle("Tab " + ++myApp.i);
myApp.tabpanel.doLayout();
}
}]
}]
});
});

Tom Strong
19 Jun 2008, 2:49 PM
Can some one explain me how to use this plugin in a grid field ? I just need some directions..

ray007
20 Jun 2008, 2:46 AM
Does it really make sense for the spinner strategies to use setRawValue() on the fields instead of just setValue()?
It circumvents the custom-formatting I'm doing in my fields, so I'm changing this at least for us locally.

ladenree
26 Jun 2008, 12:06 AM
Hi,
why the spinner does not send a change event when it spinned up/down ?

The hack is easy, just fire a change event on spin up/down.
Regards,
Olivier

mystix
26 Jun 2008, 12:35 AM
Hi,
why the spinner does not send a change event when it spinned up/down ?

The hack is easy, just fire a change event on spin up/down.
Regards,
Olivier
are you real sure you want to fire a change event on every single squeal your mousewheel makes?

you might want to buffer the mousewheel event for about a second (or more) instead, then do some calcs to decide whether or not to fire the change event.

mephi
26 Jun 2008, 5:37 AM
Hi guys, I have a little problem with spinner.

The up and down img from spinner are showing right on mozilla but on IE the 2 arrows are replaced by the double size combobox img arrow. The functionality is not affected but you can't figure it out if there is a combobox or a spinner in IE.

illuminum
8 Jul 2008, 11:03 AM
in terms of sheer utility, this is probably one of the most valuable user extensions ever created.

nbourdeau
6 Aug 2008, 10:16 AM
I think there is a bug with the spinner in Ext2.2
The widget is working properly but the buttons do not render correctly.

See attached screenshot. Maybe a CSS problem

Makor
7 Aug 2008, 11:00 AM
I have some problem - spinner do two inc on one click,
and after comment
this.repeater = new Ext.util.ClickRepeater(this.trigger);
this.repeater.on("click", this.onTriggerClick, this, {preventDefault:true});

it work correctly...

evanc
7 Aug 2008, 2:26 PM
I'm having the same issue as Makor. Any click on the triggers seems to increment/decrement on both mousedown and mouseup. Commenting out the repeater disables the functionality of being able to hold down the mouse to have it go quickly, which I like.

It looks like there was a solution posted earlier in the thread, and the code I have actually includes those changes, so there's got to be something else. I just updated to Ext 2.2. Perhaps the upgrade broke it?

K0bo
8 Aug 2008, 12:07 PM
I must have missed the v2.2 release. Haven't played with it yet. I'll look into the problem later this weekend ;)

---

Update:

I haven't found the source of the problem yet. Maybe later this week when I have some time...

Using a little piece of code from Jack to display the events fired (http://extjs.com/forum/showthread.php?p=33940#post33940):
["mousedown", Object el=Object events=Object]
["click", Object el=Object events=Object]
["spinup", Object initialConfig=Object fieldLabel=Age name=age]
["mouseup", Object el=Object events=Object]
["spinup", Object initialConfig=Object fieldLabel=Age name=age]Somehow spinup gets fired twice which makes the spinner spins twice after one click.

@nbourdeau (http://extjs.com/forum/member.php?u=23954)
I don't have the misalignment with the new version. (tried /w ff3 and ie6). Have you tried to empty your browser cache or pressed ctrl+f5 in your browser?

@Makor
The lines you commented out were fixing the problem with spinning twice after one click. Somehow in Ext 2.2 this problem has returned...

vtswingkid
20 Aug 2008, 6:24 AM
I fixed the problem with the double increment.

For some reason the line that starts with "this.trigger.un('click'" was not properly removing the onTriggerClick.

So I removed that line and overrode the initTrigger function to not include it in the first place.




//private
initTrigger :function(){
this.trigger.addClassOnOver('x-form-trigger-over');
this.trigger.addClassOnClick('x-form-trigger-click');
},

nugatto
20 Aug 2008, 10:35 PM
Thanks vtswingkid, your solution works pretty fine.
You're the man! :D

K0bo
27 Aug 2008, 12:50 PM
Released a new version which is compatible with ExtJS v2.2, includes some fixes and changes.

Thanks vtswingkid for solving the double spinning bug! ;)

temporary
27 Aug 2008, 2:03 PM
Hi k0b0, would it be possible to add an option to disable the splitter?
I really have no need for it and commented it out in the constructor... But an option would be nicer ;-)

sebrand
27 Aug 2008, 8:28 PM
Hi K0bo (http://extjs.com/forum/member.php?u=1485) ,

Thanks a lot for this great stuff, keep working! vbmenu_register("postmenu_215230", true);

sebrand
28 Aug 2008, 8:26 PM
Hi K0bo,

I was wondering if there is any way to do the spinner non editable?. I was trying with readOnly: true, but then the trigger element doesn't work.

This is my code:

var spinner = new Ext.ux.form.Spinner({
strategy:{
xtype: 'number',
minValue: 0,
maxValue: 100
},
name: 'mySpinner',
fieldLabel: 'Column number',
labelStyle: 'font-size:8pt;',
readOnly: true
});

galdaka
28 Aug 2008, 10:26 PM
Awesome!!

Live example at: http://www.jadacosta.es/extjs/examples/spinner2_v0_35/ext-spinner.html

Multiple error on lost focus in IE6.

Greetings,

singsong
31 Aug 2008, 6:40 AM
this very good!

How to set this item if the numbers instead of characters are permitted to input?

var dtYear = new Ext.ux.form.Spinner({
 fieldLabel:'Year',
 name:'dtYear',
 value:2008,
 xtype: 'number',
 strategy: new Ext.ux.form.Spinner.NumberStrategy({minValue:2000, maxValue:2100,allowDecimals:false}),
 width:120
});

var keyPress = function(e){
 var k = e.getKey();
 if(!Ext.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE)){
   return;
 }
 var c = e.getCharCode();
 var allowed = "0123456789";
  if(allowed.indexOf(String.fromCharCode(c)) === -1){
   e.stopEvent();
 }
};

//dtYear.on('keypress',keyPress);
dtYear.addListener('keypress',keyPress);

this code also can input a-z, Why?

sebrand
1 Sep 2008, 6:15 PM
You can add :
maskRe: /^[0-9]$/,
To solve it.


this very good!

How to set this item if the numbers instead of characters are permitted to input?

var dtYear = new Ext.ux.form.Spinner({
 fieldLabel:'Year',
 name:'dtYear',
 value:2008,
 xtype: 'number',
 strategy: new Ext.ux.form.Spinner.NumberStrategy({minValue:2000, maxValue:2100,allowDecimals:false}),
 width:120
});

var keyPress = function(e){
 var k = e.getKey();
 if(!Ext.isIE && (e.isSpecialKey() || k == e.BACKSPACE || k == e.DELETE)){
   return;
 }
 var c = e.getCharCode();
 var allowed = "0123456789";
  if(allowed.indexOf(String.fromCharCode(c)) === -1){
   e.stopEvent();
 }
};

//dtYear.on('keypress',keyPress);
dtYear.addListener('keypress',keyPress);

this code also can input a-z, Why?

smit_al
2 Sep 2008, 9:24 AM
I'm using the minValue and maxValue when creating a spinner field to only allow the user to enter 0-3. This works for the scroll button, but the user can still type in any value they please. This is also occurring in the demo in the first post, when I select "Convert to Number: Limited[0-10]".

smit_al
2 Sep 2008, 11:13 AM
I fixed it as follows. But is there a better way?


maxLength: 1,
maskRe: /^[0-3]/,

anotherpit
3 Sep 2008, 5:31 AM
DateStrategy sometimes forgets to pass required arguments to parent methods and causes errors:



Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
spin : function(field, down, alternate){
this.validationTask.delay(500, function(){field.validate()});
}

}

Ext.extend(Ext.ux.form.Spinner.DateStrategy, Ext.ux.form.Spinner.Strategy, {
spin : function(field, down, alternate){
Ext.ux.form.Spinner.DateStrategy.superclass.spin.call(this);
// Should be:
// Ext.ux.form.Spinner.DateStrategy.superclass.spin.apply(this, arguments);

}

});

Evolic
17 Sep 2008, 6:58 AM
Very nice widget :)

There is a small problem with Splitter displaying, when FormPanel has:
labelAlign: 'top'

I propose following code to fix it:

Ext.extend(Ext.ux.form.Spinner, Ext.form.TriggerField, {
// [...]

//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);

var form = this.findParentByType('form');
if (form) {
try {
if (form.initialConfig.labelAlign == 'top') {
var left = this.width;
if (Ext.isIE) {
left += 1;
} else {
if (Ext.isOpera) {
left += 3;
} else {
left += 2;
}
}

this.splitter.show().setLeft( left );
}
}
catch(e) {
}
}

this.proxy = this.trigger.createProxy('', this.splitter, true);
// [...]


try and catch are used to skip error message, when labelAlign is not configured.

I also noticed that this widget is not displayed correctly in Apple Safari/Google Chrome (the same rendering engine)

Evolic
17 Sep 2008, 7:37 AM
I've noticed that if I'm using NumberStrategy and I put e.g. "aaa"
nothing is changing.

I added something to fix it:

Ext.extend(Ext.ux.form.Spinner, Ext.form.TriggerField, {
// [...]

//private
onBlur : function(){
this.strategy.onSpinBlur(this);
}
})



Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
// [...]

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



Ext.extend(Ext.ux.form.Spinner.NumberStrategy, Ext.ux.form.Spinner.Strategy, {
// [...]

// Fixed function
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;

if (down === true) {
v -= incr;
} else if (down === false) {
v += incr;
}

v = (isNaN(v)) ? this.defaultValue : v;
v = this.fixBoundries(v);
field.setRawValue(v);
}
})

I hope it will be useful for you B)

pthakur
24 Sep 2008, 6:18 AM
Good stuff man!

I do have an issue. I want to change the color of the text in the textfield to which I applied this Number Spinner on the basis of the Spinner value.

At first, I tried out adding a listener method to the text field but when the spinner was operated upon it wasnt firing a textfield change event.

Then I tried adding an event listener for the Spinner itself:

spinnerArr[i].on('spin',callUpdateQuantity);

function callUpdateQuantity()
{
alert('change');
}

Now if i click on the spinner once this alert() keeps on coming endlessly. Do I need to use some other event? I also tried this with spinup and spindown events?

K0bo
18 Oct 2008, 1:47 AM
@pthakur
Instead of using the alert, try to use: window.status='hello', which should prevent the endless alerts. Alternatively if you're using FF + firebug, you can also use console.log('hello').

nbourdeau
24 Oct 2008, 1:42 PM
I've noticed that if I'm using NumberStrategy and I put e.g. "aaa"
nothing is changing.

I added something to fix it:

Ext.extend(Ext.ux.form.Spinner, Ext.form.TriggerField, {
// [...]

//private
onBlur : function(){
this.strategy.onSpinBlur(this);
}
})

Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
// [...]

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

Ext.extend(Ext.ux.form.Spinner.NumberStrategy, Ext.ux.form.Spinner.Strategy, {
// [...]

// Fixed function
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;

if (down === true) {
v -= incr;
} else if (down === false) {
v += incr;
}

v = (isNaN(v)) ? this.defaultValue : v;
v = this.fixBoundries(v);
field.setRawValue(v);
}
})I hope it will be useful for you B)


Well as i understand your code, it means that by the default, the spinner is not taking care of manually entered values ? If so, why and is this the only way to resolve this ? I'm having the problem that is the user enter a value and i call getValue() on the field, i do not get the entered value but the previous one instead ...

Iveco
5 Nov 2008, 10:34 AM
great extension, exactly what i was looking for.

love ext and it's community!

thank you very much, keep up the good work!

-----

might be useful for some other people, since 'spin' is fired after each change, here you can rely on for an update after changing



if(!delayedTaskSpinner)
{
delayedTaskSpinner = new Ext.util.DelayedTask(function()
{
console.log("UPDATED SPINNER!");

// reset for next run
delayedTaskSpinner = null;
});
delayedTaskSpinner.delay(500); // delay, since there might be more events fired in the same time,
// keep sure to wait a few ms
}

Rothariger
7 Nov 2008, 6:52 AM
i dont know if someone has made this... but i created a DataStrategy that uses the store of the field...



Ext.ux.form.Spinner.DataStrategy = function(config){
Ext.ux.form.Spinner.DataStrategy.superclass.constructor.call(this, config);
};

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

allowDecimals : false,
decimalPrecision : 0,
displayField: '',
valueField: '',
currentIndex: 0,

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

var str = field.store;
(down) ? this.currentIndex -= 1 : this.currentIndex += 1;
this.currentIndex = this.fixBoundries(this.currentIndex, field);

if(typeof str.data.items[this.currentIndex] != 'undefined')
{
field.setRawValue(str.data.items[this.currentIndex].get(this.displayField));
}
},

fixBoundries : function(v, field){
if(v < 0){
v = 0;
}
if( v > field.store.data.length - 1){
v = field.store.data.length - 1;
}

return v;
}
});



and some change in the control...



getValue: function(){
if(this.store != 'undefined' && this.store.data.length > 0)
return this.store.data.items[this.strategy.currentIndex].get(this.strategy.valueField);
else
return Ext.ux.form.Spinner.superclass.getValue.call(this);
},

setValue: function(v){
if(this.store != 'undefined' && this.store.data.length > 0)
{
var r = this.findRecord(this.strategy.valueField, v);
this.strategy.currentIndex = this.store.data.items.indexOf(r);
Ext.ux.form.Spinner.superclass.setValue.call(this, r.get(this.strategy.displayField));
}
else
return Ext.ux.form.Spinner.superclass.getValue.call(this);
},

findRecord : function(prop, value){
var record;
if(this.store.getCount() > 0){
this.store.each(function(r){
if(r.data[prop] == value){
record = r;
return false;
}
});
}
return record;
}


example of a strategy creation.




strategy: new Ext.ux.form.Spinner.DataStrategy({valueField:'company_id', displayField:'description'})





bye!

nutflakes
14 Jan 2009, 5:24 AM
great extension!
but to remove the leading zeros in the NumberStrategy I suggest to add something like the following code to the Ext.ux.form.Spinner class



validateValue : function(value){
if(this.strategy && this.strategy instanceof Ext.ux.form.Spinner.NumberStrategy) {
if(!isNaN(value)) {
this.setRawValue(this.strategy.fixBoundries(parseInt(value)));
return true;

} else {
return false;
}

} else {
return true;

}
},


cheers,
uwe

paulwang727
10 Feb 2009, 9:02 AM
is anyone else having issues clicking on the down arrow in IE?

nomack84
12 Feb 2009, 6:37 AM
Form spinner is a great component, it will be good if the Ext team put it into the framework. But I have an issue from a long time ago. When I tried to use it in a panel with layout card, witch is the container of some form panel, containing the spinner field, the split is not render correctly. Anyone have this trouble too? How can I fixed it?

cnesbit
24 Feb 2009, 7:36 AM
First off, let me say this spinner control is GREAT! It would inspire me to start building a few controls of my own, but I haven't come up with any ideas of new controls yet. :)

So, here's my thing...
I've declared a time spinner in my extjs like so:


...
items: new Ext.ux.form.Spinner({
fieldLabel: 'Clock In',
name: 'clockin',
strategy: new Ext.ux.form.Spinner.TimeStrategy({
minValue:currentDate.getHours()+":"+currentDate.getMinutes())
})
})
...
whenever I use the up/down arrows on my spinner control, firebug gives me this error:


field is undefined
https://.../SpinnerStrategy.js
Line 46
So, I looked at the offending function, and here's what I see, for clarification:


43 Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
44 ...
45 spin : function(field, down, alternate){
46 this.validationTask.delay(500, function(){field.validate()});
47 //extend
48 },
49 ...
50 });
It appears that "field" in the phrase "field.validate()" is causing a problem. As a consequence I cannot seem to validate the control in any fashion, say if the user decides to type "eleven thirty" instead of "11:30".

Being an avid programmer, and the kinda programmer who likes to make my web pages as "dummy proof" as possible, I'd like to get the validation correct. But I can't quite follow what the "field" "down" and "alternate" variables are in this function, much less why the "field" variable is supposedly undefined.

Any known solution to this bug, or some help fixing it? (if it even is a bug?)

Thanks in advance!
cnesbit

mystix
24 Feb 2009, 8:17 AM
First off, let me say this spinner control is GREAT! It would inspire me to start building a few controls of my own, but I haven't come up with any ideas of new controls yet. :)

So, here's my thing...
I've declared a time spinner in my extjs like so:


...
items: new Ext.ux.form.Spinner({
fieldLabel: 'Clock In',
name: 'clockin',
strategy: new Ext.ux.form.Spinner.TimeStrategy({
minValue:currentDate.getHours()+":"+currentDate.getMinutes())
})
})
...
whenever I use the up/down arrows on my spinner control, firebug gives me this error:


field is undefined
https://.../SpinnerStrategy.js
Line 46
So, I looked at the offending function, and here's what I see, for clarification:


43 Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
44 ...
45 spin : function(field, down, alternate){
46 this.validationTask.delay(500, function(){field.validate()});
47 //extend
48 },
49 ...
50 });
It appears that "field" in the phrase "field.validate()" is causing a problem. As a consequence I cannot seem to validate the control in any fashion, say if the user decides to type "eleven thirty" instead of "11:30".

Being an avid programmer, and the kinda programmer who likes to make my web pages as "dummy proof" as possible, I'd like to get the validation correct. But I can't quite follow what the "field" "down" and "alternate" variables are in this function, much less why the "field" variable is supposedly undefined.

Any known solution to this bug, or some help fixing it? (if it even is a bug?)

Thanks in advance!
cnesbit
haven't dug into the code, but that bit you posted looks incorrect.

try changing it to this instead:


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

cnesbit
24 Feb 2009, 8:27 AM
You would think that would work, but actually, the spinner won't show any times now when I click the spinner buttons, whereas it did with the original 0.35 code. ...still no validation.

Also, that does not change the fact that "field is undefined". I did notice that the TimeStrategy has not custom "spin" function, making sense that it would inherit the default "spin" function. Any chance someone has written a custom "spin" function for the "TimeStrategy"?

mystix
24 Feb 2009, 8:29 AM
You would think that would work, but actually, the spinner won't show any times now when I click the spinner buttons, whereas it did with the original 0.35 code. ...still no validation.

Also, that does not change the fact that "field is undefined". I did notice that the TimeStrategy has not custom "spin" function, making sense that it would inherit the default "spin" function. Any chance someone has written a custom "spin" function for the "TimeStrategy"?

haha.. i was thinking about that right after i posted. oh well. cheers :"> ~o)

cnesbit
24 Feb 2009, 8:47 AM
So, what your telling me is, I'm on my own if I wanna use this as a Time Spinner, unless I don't care about validation?

Don't get me wrong. I'd be up for the challenge, but custom extjs controls is very new to me (I've only been extjs'ing for a couple months now). I could use a little push, if anyone has something to offer.

***EDIT***
I FIXED IT! I managed to fix the code on my own, but here's a summary of my changes, for the record:

SpinnerStrategy.js:


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

...
basically, TimeStrategy extends DateStrategy, which was missing the highlighted code. I was getting the error "field is undefined" because "field" was not getting passed from DateStrategy.spin to Strategy.spin.

Once this change was made, all was well with the world. Hope this helps someone else besides me so I can be useful to the extjs community. I'd rather that, than to be one of those noobs that never seem to be able to figure it out. :)

BTW, it works with Strategy.spin coded as I originally posted:


spin : function(field, down, alternate){
//this.validationTask.delay(500, field.validate, field);
this.validationTask.delay(500, function(){field.validate()});
//extend
},
cnesbit

mystix
24 Feb 2009, 9:02 AM
how does your code defer from the sample page's?
http://members.upc.nl/j.chim/ext/spinner2/ext-spinner.html
http://members.upc.nl/j.chim/ext/spinner2/ext-spinner.js

cnesbit
24 Feb 2009, 2:22 PM
how does your code defer from the sample page's?
http://members.upc.nl/j.chim/ext/spinner2/ext-spinner.html
http://members.upc.nl/j.chim/ext/spinner2/ext-spinner.js

The only relevant difference that I know of is in the SpinnerStrategy.js file, as I described in my last post.

mystix
24 Feb 2009, 5:39 PM
The only relevant difference that I know of is in the SpinnerStrategy.js file, as I described in my last post.
that's really odd then.

are you on Ext 2.0 / 2.0.2 / 2.1 / 2.2 / 2.2.1?

as far as i can tell (from his public demo), the OP's only used his plugin in 2.0.

cnesbit
25 Feb 2009, 5:11 AM
that's really odd then.

are you on Ext 2.0 / 2.0.2 / 2.1 / 2.2 / 2.2.1?

as far as i can tell (from his public demo), the OP's only used his plugin in 2.0.

Sorry for my ignorance, the extjs configuration that my team and I are using was installed before I joined the project. Any way I can tell by looking somewhere in, say, ext-all.js or something? ...I know we're using at least 2.0.

here's the code I am using to create/call my spinner controls:


...
items: [ new Ext.ux.form.Spinner({
fieldLabel: 'Clock In',
name: 'clockin',
id: 'clockin',
value: currentTime, //currentTime is a js var that I pre-created
strategy: new Ext.ux.form.Spinner.TimeStrategy({})
}), new Ext.ux.form.Spinner({
fieldLabel: 'Clock Out',
name: 'clockout',
id: 'clockout',
value: currentTime, //currentTime is a js var that I pre-created
strategy: new Ext.ux.form.Spinner.TimeStrategy({})
})
]
...

mjlecomte
25 Feb 2009, 5:21 AM
I can tell by looking somewhere in, say, ext-all.js or something? ...
Just type Ext.version in firebug console

cnesbit
25 Feb 2009, 5:22 AM
Just type Ext.version in firebug console

heh, that's a cool little trick :) I am easily amused. anyway, the output I receive tells me I'm on version "2.0.2"

mvarshavsky
5 Mar 2009, 12:36 AM
First of all, I want to thank K0bo for this awesome extension. Props!
I've seen a few people mention that their arrow controls showed up on the left side of the input field instead of the right in FF2. I was experiencing the same problem and in my case traced it down to my own style which set .XXX * (where XXX was class of input's container div) to {float:left;}, so solution ended up being:



.x-form-field-wrap .x-form-spinner-trigger {float:none !important;}


another option that worked for me was to set the above to position:relative

mask_hot
6 Mar 2009, 3:53 AM
Hello,

I have an issue with the spinner ux when I try to load data into my form, the spinner fileds are not filled.

here is my code :


,{
title:'Profil',
defaults:{width:100},
defaultType: 'uxspinner',
items: [{
fieldLabel: 'Puissance',
name: 'pui',
strategy: {
xtype:'number'
,minValue:0
,maxValue:100
}

},{
fieldLabel: 'Physique',
name: 'phy',
strategy: {
xtype:'number'
,minValue:0
,maxValue:100
}
},{
fieldLabel: 'Technique',
name: 'tec',
strategy: {
xtype:'number'
,minValue:0
,maxValue:100
}
}, {
fieldLabel: 'Attaque',
name: 'att',
strategy: {
xtype:'number'
,minValue:0
,maxValue:100
}
}, {
fieldLabel: 'Vitesse',
name: 'vit',
strategy: {
xtype:'number'
,minValue:0
,maxValue:100
}
}
, {
fieldLabel: 'D&eacute;fense',
name: 'def',
strategy: {
xtype:'number'
,minValue:0
,maxValue:100
}
}

]


My form contains a tabPanel and the last panel contains the spinners.
I verified my json and I have the right names :


"pui":"50","phy":"50","tec":"50","vit":"50","def"
:"50","att":"50"


All my other fields in others tabs are well filled.

xwang2
31 Mar 2009, 7:21 AM
I put uxspinner as one of the items in Ext.FormPanel, which is displayed in a Ext.Window along with other panels. The spinner shows up fine when first loading the popup window by clicking on a button. However when I close the window, and clicking the button to load the window again, the spinner disappear. I have to hit Refresh in the browser, and then hit the button to load the window to get the spinner show up again. All other controls show up fine. I have tried the xtype and the new Ext.ux.form.Spinner ways. They both have this problem. Anybody has any idea? Thanks in advance!

BKrisz79
6 Apr 2009, 8:21 AM
I have a little error message in firebug. I put this on a formpanel:


new Ext.ux.form.Spinner({
id: 'acbvgff',
fieldLabel: 'Időpont',
name: 'event_time',
value: '09:00',
strategy: new Ext.ux.form.Spinner.TimeStrategy()
})

if ypu want here is the whole code:

var fpProjectEvent = new Ext.form.FormPanel({
id: 'fpEditPRJE',
baseCls: 'x-plain',
waitMsgTarget: true,
labelAlign: 'left',
frame: false,
header: false,
hideBorders: true,
bodyStyle:'padding:5px',
border: false,
autoHeight: true,
buttonAlign: 'center',
width: '100%',
labelWidth: 100,
defaults: [{validationEvent: 'onBlur'}],

items: [{
id: 'hPRJEAction',
xtype: 'hidden',
name: 'action',
value: 'insertPRJE'
},{
id: 'hPRJEPrjeid',
xtype: 'hidden',
name: 'prjeid',
value: 0
},{
id: 'hPRJEPrjid',
xtype: 'hidden',
name: 'prjid',
value: 0
},{
xtype: 'textfield',
fieldLabel: 'Esemény címe',
id: 'tfPRJEName',
name: 'name',
maxLength: 150,
allowBlank: false,
anchor: '97%',
value: ''
},{
xtype: 'combo',
id: 'cboPRJETagid',
fieldLabel: 'Kategória',
emptyText: 'Válaszon...',
name: 'tagid',
store: App.builder.MainData.storeGeneralTaskGroups,
displayField: 'name',
hiddenName: 'tagid',
valueField: 'tagid',
typeAhead: true,
forceSelection: true,
triggerAction: 'all',
selectOnFocus: true,
minChars: 1,
queryDelay: 50,
mode: 'remote',
allowBlank: false,
anchor: '97%'
},{
layout: 'column',
baseCls: 'x-plain',
items: [{
columnWidth: .33,
layout: 'form',
baseCls: 'x-plain',
items: [{
xtype: 'datefield',
fieldLabel: 'Esemény dátuma',
name: 'event_date',
id: 'dfPRJEEventDate',
anchor: '92%',
allowBlank: false
}]
},{
columnWidth: .34,
layout: 'form',
baseCls: 'x-plain',
items: [
new Ext.ux.form.Spinner({
id: 'acbvgff',
fieldLabel: 'Időpont',
name: 'event_time',
value: '09:00',
strategy: new Ext.ux.form.Spinner.TimeStrategy()
})
]
},{
columnWidth: .33,
layout: 'form',
baseCls: 'x-plain',
items: [{
xtype: 'checkbox',
id: 'chbPRJEIntoCalendar',
fieldLabel: 'Naptárba',
labelSeparator: '?',
style:'margin-top:2px',
name: 'into_calendar'
}]
}]
},{
xtype:'tabpanel',
id: 'tpPRJEForm',
plain: true,
activeTab: 0,
height: 250,
border: true,
deferredRender: false,
items: [{
cls: 'x-plain',
id: 'tpPRJEDetails',
title: 'Leírás',
layout: 'fit',
items: {
xtype: 'htmleditor',
id: 'hePRJEDetails',
name: 'details',
listeners: {
initialize: function(el) {
}
}
}
},{
cls: 'x-plain',
id: 'tpPRJEUploadProjectEventFiles',
title: 'Pályázati dokumentumok',
layout: 'fit',
items: [gridPanelProjectEventFiles]
}]
}],
buttons: [{
text: 'Küldés',
type: 'submit',
cls: 'x-btn-text-icon',
icon: 'images/icons/tick.png',
formBind: true,
handler: function(){
fpProjectEvent.form.submit({
url: '_ajax/project_events.php',
method: 'POST',
success: function(form,action) {
wProjectEvent.hide();
gridProjectEventsUpdate();
},
failure: function(form, action) {
var ajaxResponse = Ext.decode(action.response.responseText);
Ext.Msg.alert(ajaxResponse.messageTitle,ajaxResponse.message);
}
});
}
},{
text: 'Rögzít',
type: 'submit',
cls: 'x-btn-text-icon',
icon: 'images/icons/tick.png',
formBind: true,
handler: function(){
fpProjectEvent.form.submit({
url: '_ajax/project_events.php',
method: 'POST',
success: function(form,action) {
var ajaxResponse = Ext.decode(action.response.responseText);
Ext.getCmp('hPRJEPrjeid').setValue(ajaxResponse.prjeid);
Ext.getCmp('tpPRJEUploadProjectEventFiles').enable();
Ext.apply(gridPanelProjectEventFiles.store.baseParams,{
prjeid: ajaxResponse.prjeid,
start: 0,
limit: perPage
});
gridPanelProjectEventFiles.store.load();
gridProjectEventsUpdate();
},
failure: function(form, action) {
var ajaxResponse = Ext.decode(action.response.responseText);
Ext.Msg.alert(ajaxResponse.messageTitle,ajaxResponse.message);
}
});
}
},{
text: 'Mégsem',
cls: 'x-btn-text-icon',
icon: 'images/icons/cross.png',
handler: function(){
wProjectEvent.hide();
}
}]
});

When I open the formpanel and click on the up arrow it works but 500msec later I get this error message in firebug.



SpinnerS...rategy.js (sor 46)

field is undefined
spin()()SpinnerS...rategy.js (sor 46)
call()()ext-all-debug.js (sor 6592)
[Break on this error] this.validationTask.delay(500, function(){field.validate()});

Any idea to solve this problem?

kavih7
21 Apr 2009, 9:59 PM
I've noticed that if I'm using NumberStrategy and I put e.g. "aaa"
nothing is changing.

I added something to fix it:

Ext.extend(Ext.ux.form.Spinner, Ext.form.TriggerField, {
// [...]

//private
onBlur : function(){
this.strategy.onSpinBlur(this);
}
})



Ext.extend(Ext.ux.form.Spinner.Strategy, Ext.util.Observable, {
// [...]

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



Ext.extend(Ext.ux.form.Spinner.NumberStrategy, Ext.ux.form.Spinner.Strategy, {
// [...]

// Fixed function
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;

if (down === true) {
v -= incr;
} else if (down === false) {
v += incr;
}

v = (isNaN(v)) ? this.defaultValue : v;
v = this.fixBoundries(v);
field.setRawValue(v);
}
})

I hope it will be useful for you B)

Yes, this was useful! I abstracted your code slightly, so that spin validation will work for any strategy. I only tested it on using a number strategy, though:



Ext.override(Ext.ux.form.Spinner, {
onBlur : function()
{
this.strategy.onSpinBlur(this);
}
});

Ext.override(Ext.ux.form.Spinner.Strategy, {
onSpinBlur : function(field)
{
var value = field.getValue()

if (value != this.fixBoundries(value))
{
this.spin(field, null, false);
}
}
});

aray
28 Apr 2009, 11:52 PM
nice~

Richie1985
14 May 2009, 1:27 AM
i have a big problem,

when i add a spinner field in a toolbar, in firefox i can click the down button, in ie 6 are onle showing the scroll cursor:

http://img526.imageshack.us/img526/3219/unbenanntj.jpg

can you help me please?

thx


this.dauer = new Ext.ux.form.Spinner({
hidden: true, disabled: true, name: 'menge', emptyText: 'Dauer', width: 60
,strategy:new Ext.ux.form.Spinner.TimeStrategy({defaultValue: new Date(0,0,0,0,0,0) })
});

anotherpit
2 Jun 2009, 5:24 AM
@Richie1985
I had the same problem here. Spinner.css need to be fixed:

.x-form-field-wrap .x-form-spinner-splitter {
line-height:1px;
font-size:1px;
background:transparent url(/script/spinner/spinner-split.gif) no-repeat 0 0;
position:absolute;
cursor: n-resize;
overflow: hidden;
}

Richie1985
3 Jun 2009, 4:16 AM
@Richie1985
I had the same problem here. Spinner.css need to be fixed:

.x-form-field-wrap .x-form-spinner-splitter {
line-height:1px;
font-size:1px;
background:transparent url(/script/spinner/spinner-split.gif) no-repeat 0 0;
position:absolute;
cursor: n-resize;
overflow: hidden;
}

big thanks :)

tarini
13 Jul 2009, 2:43 AM
great job!
what about extjs3 integration?

funkju
23 Jul 2009, 12:30 PM
Here is Ext.ux.form.Spinner.DurationStrategy that I wrote for an application. It will display a value in the form of:

1 year, 2 month, 3 day, 1 hour, 2 min, 24 sec, 133 ms

You can specify a lowest and highest precision in the config, such as:

lowestPrecision: 'min',
highestPrecision: 'day'

will provide

3 day, 1 hour, 2 min

Hope it can be useful to someone.



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

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

delimiters : [
['ms', 1],
['sec', 1000],
['min', 60000],
['hour', 3600000],
['day', 86400000],
['month', 2592000000],
['year', 31104000000]
],


lowestPrecision : 'ms',
highestPrecision : 'year',
defaultValue : '0 sec',

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

//String to Value
var durSplit = field.getValue().split(", ");
var v = 0;
var incr = 1;
for (var i = 0; i<durSplit.length; i++) {
for (var j = 0; j<this.delimiters.length; j++) {
str = durSplit[i];
del = this.delimiters[j][0];
mult = this.delimiters[j][1];
if (str.indexOf(del) != -1) {
str = str.replace(del,"");
if (str.indexOf(",") != -1) str = str.replace(",","");
v += parseFloat(str) * mult;
}

//Find the increment value
if (del == this.lowestPrecision) incr = mult;
}
}

//Increment
(down == true) ? v -= incr : v += incr;
v = (v > this.maxValue) ? this.maxValue : v;
v = (v < this.minValue) ? this.minValue : v;

//Val to String
var str = "";
var metHighest = false;
for (var i = this.delimiters.length-1; i >=0 ; i--) {
del = this.delimiters[i][0];
mult = this.delimiters[i][1];
if (del == this.highestPrecision) {
metHighest = true;
}
if (metHighest) {
t = Math.floor(v/mult);
str += t + " " + del + ", ";
v -= t * mult;
}
if (del == this.lowestPrecision) {
break;
}
}
//chop off last space
str = str.substr(0,str.length-2);

str = (str == "") ? this.defaultValue : str;

field.setRawValue(str);
}

});

ThankMyLove
31 Jul 2009, 3:55 AM
good!

cdj
1 Aug 2009, 10:12 PM
excellent extension!

arunpjohny
31 Aug 2009, 10:40 PM
Thanks for this greate extension.

I was facing some issue related to a double action in the triggerfield. ie, if I click once the value was getting decreased/increased by 2 instead of 1.

My investigation into this show me the following issue in removing the click event in the trigger object.

In the TriggerField class the click event is registered as given below

this.trigger.on("click", this.onTriggerClick, this, {preventDefault:true});Then in the initSpinner() method we are removing the event listener as given below

this.trigger.un("click", this.onTriggerClick);Here we are not passing the scope variable. This is causing some issue for me since the scopes of the registered event and the scope passed through this un() method is different, it is not removing the event listener.

I think the code to remove the event listener has to be modified as given

this.trigger.un("click", this.onTriggerClick, this);.

This works fine for me.

Minnow
1 Sep 2009, 7:08 AM
I needed to use a number strategy that included a Unit of Measure after a number, so I've extended the NumberStrategy to work with this.

For example:

5 %
10 %
15 %

- or -

1 Year
2 Years

It alters the field's get/set RawValue methods as shown below.



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

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

/** Example usage of uom config option:
* uom : '%' -- All values will use the same uom
* - or -
* uom : {
* 1 : 'Year', -- to set the uom for a specific value
* defaultUom : 'Years' -- REQUIRED for object definition -- the default uom for any unmatched value
* empty : '' -- if '' (empty string) is encountered, use this uom
* }
**/
uom : null,

init : function(field) {
// format the intial value
this.rawValue = field.value;
field.value = this.formatValue(this.rawValue);
// store the field's original setRawValue method
var setValue = field.setValue.createDelegate(field);
var setRawValue = field.setRawValue.createDelegate(field);

// overrides
field.getRawValue = (function() {
return this.rawValue;
}).createDelegate(this);

field.setValue = (function(value) {
this.rawValue = parseFloat(value);
setValue(this.formatValue(this.rawValue));
}).createDelegate(this);

field.setRawValue = (function(value) {
this.rawValue = parseFloat(value);
setRawValue(this.formatValue(this.rawValue));
}).createDelegate(this);

Ext.ux.form.Spinner.UOMStrategy.superclass.init.call(this, field);
},

formatValue : function(value) {
if (value === undefined) { return value; }

if (typeof this.uom === 'string' && this.uom.length) {
return value + ' ' + this.uom;
} else if (typeof value === 'string' && !value.length && this.uom.empty !== undefined) {
return this.uom.empty;
} else if (this.uom[value] || this.uom.defaultUom) {
return value + ' ' + (this.uom[value] || this.uom.defaultUom);
}
return value;
}
});


It also requires an addition to Spinner.js where you need to add the following to the end of initSpinner:



initSpinner : function(){
...
if (typeof this.strategy.init === 'function') {
this.strategy.init(this);
}
},


I've tested quickly with validation and it seems to work for my purposes. Enjoy.

Minnow
1 Sep 2009, 8:21 AM
As a further to my previous post, we also need some user entry handling so that we can stabilize the value (at least to something a little bit more reasonable).

For this, I've captured the field's change event as it only gets triggered when the user manually edits the field.

This really needs to start from the Spinner.Strategy base class, which can be altered as follows:



init : function(field) {
field.on({
change : this.onFieldChange,
scope : this
});
},

onFieldChange : function(field, value) {
field.setRawValue(value);
},


I've added the following override to my local copy of NumberStrategy as follows:



onFieldChange : function(field, value) {
// short hand to make this fit in the forum CODE window
var superclass = Ext.ux.form.Spinner.NumberStrategy.superclass;
superclass.onFieldChange.call(this, field, this.fixBoundries(parseFloat(value)));
},


This could be extended across the other strategies as well, but as I don't really need them at this point I've not looked into them.

(Note: don't forget to add the "this.strategy.init(this);" call to initSpinner as in my previous post)

TheBerliner
3 Sep 2009, 10:12 PM
Hello experts,

I am new to EXT 3 and trying to use the Spinner widget. I use the 3.0 version contained in the examples.

Whatever I do, the label will not show up correctly.

I build a "real" scenerio and a test one.

Real must be a Panel "Tools" with absolute layout, as the spinners are placed among buttons and other fields using explicit x/y coordinates. The spinner labels do not show at al. See "Tools" column in snapshot.

Second, just for testing I added similar spinner fields (same settings) to a form panel ("Details") and the labels appear on the panel top neglecting the x/y settings of the spinners. Using labelWidth seems to be ignored.

Is there any change to use the spinner widget with a label properly?

Second: What is the cause that the entry fields have a smaller height than the entire spinner? All attempts to set the height were in vain.

Thank you for any hint.

Here the code for the spinners:


var buttonPorECToolsZoomSet5 = new Ext.ux.form.SpinnerField({
name: 'buttonPorECToolsZoomSet5',
id: 'buttonPorECToolsZoomSet5',
fieldLabel: 'Z%', //appear at a different y position
cls: 'csButtonECZoomSet',
tooltip: tr.mm_buttonPorECToolsZoomSet,
allowDecimals: false,
minValue: app.zoomFactorMin,
maxValue: app.zoomFactorMax,
incrementValue: 10,
alternateIncrementValue: 25,
accelerate: true,
autoWidth: false,
labelWidth: 50, //is ignored
height: 36,
width: 70,
x: 0,
y: 50,
handler: function (){zoomPercent(this);}
});


var buttonPorECToolsZoomSet6 = new Ext.ux.form.SpinnerField({
name: 'buttonPorECToolsZoomSet6',
id: 'buttonPorECToolsZoomSet6',
fieldLabel: 'Text', //appear at a different y position
cls: 'csButtonECZoomSet',
tooltip: tr.mm_buttonPorECToolsZoomSet,
allowDecimals: false,
minValue: app.zoomFactorMin,
maxValue: app.zoomFactorMax,
incrementValue: 10,
alternateIncrementValue: 25,
accelerate: true,
autoWidth: false,
// labelWidth: 50, makes no difference
height: 36,
width: 70,
x: 0,
y: 100, //needed for tools panel
handler: function (){zoomPercent(this);}
});

jsakalos
4 Sep 2009, 12:39 AM
Labels are created by FormLayout not by fields themselves.

TheBerliner
4 Sep 2009, 1:31 AM
Labels are created by FormLayout not by fields themselves.
Dakujem pekne,

And with regards to Jack Slocum: This is a great conceptual mistake that will cause me a lot of headaches in the future.

In other words, one has to create such labels separately as text fields?

If so, this would be a great nonsense.

mystix
4 Sep 2009, 1:47 AM
Dakujem pekne,

And with regards to Jack Slocum: This is a great conceptual mistake that will cause me a lot of headaches in the future.

In other words, one has to create such labels separately as text fields?


fortunately not, or i would've screamed "Utter nonsense!" a long time ago.

Ext.form.Fields are Components which are managed by a Container (e.g. FormPanel).

A Container (and all children thereof) has a layout scheme (e.g. ContainerLayout -- the default layout for all Containers -- or FormLayout, etc).

A Layout manages Field arrangement (i.e. layout) and (re)sizing.

A FormLayout, on top of performing its basic duties as a layout manager, has some additional responbilities -- one of them being managing the display of Field labels, and their arrangement + (re)sizing.


p.s. i'm not sure if something got lost in translation from your native tongue to English, but your written words (from the post above, and from past posts i've seen) do carry an aggressive, and might i humbly suggest, holier-than-thou tone which will more often than not be treated as both offensive and rude. just thought i should point that out.


[edit]
note: i'm explaining the Container / Layout / Field hierarchy from the perspective of one who generates the entire user interface from javascript alone -- there is no rendering of components to existing html <div>s, neither is there any transformation of ordinary html controls (e.g. <select>) into Ext Components (e.g. ComboBox); there is only 1 giant Container -- the Viewport -- which contains everything else.

TheBerliner
4 Sep 2009, 5:39 AM
Hello Mystix,

Very glad to hear! I have seen a UI system, which implements this fancy idea of separating fields from their labels into two entities. Very, very stupid! Has cost me a lot of wasted time with no gain.

However, if I understand you correctly, the result of what has been implemented in Ext seems to be essentially the same as what Saki stated? Only that it's the layout attached to the container that places the labels regardless of the data inide the widget object.

You wrote: "A FormLayout ... managing the display of Field labels, and their arrangement + (re)sizing."

In other words, no matter what the widgets contain, the FormLayout (inside the container) does its own thing. That means that the wrong placing of field labels far away from their second part, the data part, is - in this concept - correct?

Now, it that is true then this is just the mistake that I was fearing. It does not make any difference if the panel or its layout manager is the evil-doer. The result is wrong and evil, because it separates two entities, which belong together, or rather places them separately.

As a result, a mixed and correct palacing with explicit co-ordinates inside a non-form container is not possible?

But perhaps or hopefully did I misunderstand you - and that is then not a language problem.

To give you a hint how to solve this in a simple and effective form:

Such fields normally build logical chains. Often one depends on another. It would therefore be very useful to chain such widgets in a successor/predecessor chain with x or y offsets and relations and with the possibility to place single widgets on absolute co-ordinates, either to start a chain, or part of it, or as exceptions.

I implemented this, together with multi-dimensional containers, in a database publishing system. Very easy to place and highly flexible and simple to understand even for laymen.

I am curious to read if I will have problems with this implementation or if its my limited knowledge (also due to the frugal documentation, which drives me nuts every day).

------------------
Regarding your P.S.

English is only "almost" my "native tongue", not only because it's a very much simplified and drastically reduced version of my native tonue with the addition of lots of Romanic words. When hearing me, North American typically think I was English.

No, dakujem pekne means thank you "nicely" in Slovak. Had girl friends from this beautiful country.

And my question mark and my clear state "if so..." leave room for the case of error, which you confirm - or rather not.

We probably have the "problem" (not "issue") that you are presumably from "across the pont", as Animal stated recently, and I am European where words are still used in their true and honest meaning. We are not (yet) raped by political correctness. We die and don't "pass away" (stupid term) and we have "problems" not "issues". Thus, our language lies less, unfortunately not necessarily the speakers.

mystix
4 Sep 2009, 10:36 AM
In other words, no matter what the widgets contain, the FormLayout (inside the container) does its own thing.

the FormLayout lays things out. it doesn't "do its own thing".



That means that the wrong placing of field labels far away from their second part, the data part, is - in this concept - correct?

i do not understand what you're saying here. please clarify.



The result is wrong and evil, because it separates two entities, which belong together, or rather places them separately.

if by that you mean it's "wrong" to not wrap an <input> field within a <label> tag, thus keeping them "together", then it's open for debate -- it's neither "evil" to wrap <input>s within <label>s, neither is it "evil" to place them "separately", side-by-side.



As a result, a mixed and correct palacing with explicit co-ordinates inside a non-form container is not possible?

A FormLayout can manage absolute page co-ordinates
(refer to the layout browser -> combination examples -> absolute layout form (http://www.extjs.com/deploy/dev/examples/layout-browser/layout-browser.html) example).

A Container is just that -- it contains other Components. It can be a "non-form" container, but it'll handle "mixed and correct palacing with explicit co-ordinates" if it is set up to use a FormLayout.



Such fields normally build logical chains. Often one depends on another. It would therefore be very useful to chain such widgets in a successor/predecessor chain with x or y offsets and relations and with the possibility to place single widgets on absolute co-ordinates, either to start a chain, or part of it, or as exceptions.

i like this idea a lot, and would like to see you bring this to fruition when you overcome the "minimal and frugal" documentation (be proactive -- write the documentation as you would like to see it (http://www.extjs.com/forum/showthread.php?t=40317)).




We probably have the "problem" (not "issue") that you are presumably from "across the pont", as Animal stated recently, and I am European where words are still used in their true and honest meaning. We are not (yet) raped by political correctness. We die and don't "pass away" (stupid term) and we have "problems" not "issues". Thus, our language lies less, unfortunately not necessarily the speakers.

It is one thing to be forthright. It is quite another to be rude.
It is always wise to season our words - we won't know when we might have to eat them.

TheBerliner
7 Sep 2009, 5:07 AM
the FormLayout lays things out. it doesn't "do its own thing".
Well, it obviously places the labels at a very different position far away from the data part of the fields. That is what I call wrong and "their own thing."

See: Data fields (no matter what type, input fields, check / radion boxes etc) all consist of two parts:
- some label
- some entry / action area.
They belong together. Labels are placed on the left or right and sometimes above or below the data part. And it seems that Ext wraps them far apart. No user would ever expect the label far away from the entry area. So why this?

The container cannot and should not know (better) where to place these parts. The widget does alone by having x/y data. Unless you have chained widgets with predecessors etc but that does not exist in Ext.


if by that you mean it's "wrong" to not wrap an <input> field within a <label> tag, thus keeping them "together", then it's open for debate -- it's neither "evil" to wrap <input>s within <label>s, neither is it "evil" to place them "separately", side-by-side.
In my example, there is only a "wrapping apart" by placing them at a substantial space difference between label and field. But maybe, I misunderstand you.


A FormLayout can manage absolute page co-ordinates
(refer to the layout browser -> combination examples -> absolute layout form example).
Well, I cannot exclude that I made a mistake. This is why I posted the code. But whatever I did, labels and entry parts were always placed very far away from another. The x/y co-ordinates given to the widget were ignored for the label part and obeyed for the entry part.

So if I understand you correctly, there is a conceptual difference between Ext's implementation and what I would consider a feasible placing of widgets. Thus, I will have to find a way to live with this situation. Unfortunately, as I see this (maybe I am wrong) at the moment, there seems to be a great conceptual mistake in the placing of widget labels.


i like this idea a lot, and would like to see you bring this to fruition
Well, my idea is to later extend my JS generator to use this database publishing package to generate JS UI code for Ext and also for Flash. But that is still some time down the road.


when you overcome the "minimal and frugal" documentation (be proactive -- write the documentation as you would like to see it).
Concerning the documentation:

1) Ext is essentially a comercial product. Now, my customers would call me nuts or worse if I was asking them to write their doc themselves. This idea would be perceived as being absurd at least by my customers - beyond the fact that it needs a domain expert to do so. I cannot see why the situation should be any different here.

A proper usable documentation is simply an essential part of any product, namely of software. And besides that: This form of support costs Ext multiple times more than having a proper doc written by some professionals. I wasted some 40-50% of my time just because of this lousy documentation. And I think I am a good example: On one side new to Ext and JS, on the other very expecienced in (true) o-o concepts and implementations. Thus, I think, a good test candidate for your documentation.

And this loss of time due to the extremely bad state of the Ext doc makes my angry.

2) A good documentation needs a domain expert and an author. Developers are no good authors, not only because their strength is rarely verbal but rather mathematical. One excludes the other. And I am not an EXT domain expert and will never be.

3) My strong impression is that the Ext development and management team has no interest whatsoever in customer feedback. My several detailed emails with proposals were unanswered and, I suppose, not even really recognized.

------------------------OT:
As for the language: I am sure I was not rude, certainly not compared to what I was told by people writing here with highest posting scores, because I dared to criticize the documentation. And besides that, my "If so, this would be a great nonsense." was clearly containing an "if". Problem 1 is that North Americans have been so extremely brain-washed by PC that this often distorts their reality, problem 2 is that PC is a dictatorial attempt to stop people from thinking and from the truth and the problem 3 is that, as always, North Americans think that their own "standards" are valid for "the rest of world", which is not true and never will be (just like for their insane laws or their idiotic patents system). This is why they are so increasingly popular in other countries with old and great cultures. But all of this was just meant in general, of course, to make you aware of this.

mystix
7 Sep 2009, 9:37 AM
before i respond to the latter half your post, let me state for the record:
i am a forum volunteer, so i'll address only what i can in my capacity as a volunteer

i have no comments on the first half of your post
-- i think it makes for a potentially healthy technical discussion.

now on to my reply proper.



Concerning the documentation:

1) Ext is essentially a comercial product. Now, my customers would call me nuts or worse if I was asking them to write their doc themselves. This idea would be perceived as being absurd at least by my customers - beyond the fact that it needs a domain expert to do so. I cannot see why the situation should be any different here.

A proper usable documentation is simply an essential part of any product, namely of software. And besides that: This form of support costs Ext multiple times more than having a proper doc written by some professionals. I wasted some 40-50% of my time just because of this lousy documentation. And I think I am a good example: On one side new to Ext and JS, on the other very expecienced in (true) o-o concepts and implementations. Thus, I think, a good test candidate for your documentation.

And this loss of time due to the extremely bad state of the Ext doc makes my angry.

i'm not requesting that you compose Bach's Air on G String.
i'm attempting to address your desire to see the "minimal and frugal" documentation expanded and improved upon.

you've quite obviously spotted a minefield of mistakes / inadequacies in the documentation, and you definitely qualify as someone who has had an absolutely lousy first-hand experience with the documentation. who better than you to point these out -- the thread i pointed you to and the Documentation Bugs thread are 2 good places where you can contribute observations / suggestions / improvements.

though there is a commerical side to Ext, the documentation is almost entirely community-driven. which is why i think it completely absurd that a large number of people who complain about the documentation do so without being able to describe the cause of their misery -- i equate this to patients who insist to their doctors that there must be something wrong with them, but they just can't say what -- when there are many others that have come forward with suggestions to help make it better.




And besides that, my "If so, this would be a great nonsense." was clearly containing an "if".

i'm not sure which portion of my reply gave you the impression that i was offended by that. rest assured -- that was not the offending bit.




As for the language: I am sure I was not rude, certainly not compared to what I was told by people writing here with highest posting scores, because I dared to criticize the documentation.

let me be very clear then: it was you were very rude.
(and it had absolutely nothing to do with your criticism of the documentation).
to make absolutely certain that we're on the same page, this is what i found offensive:


We probably have the "problem" (not "issue") that you are presumably from "across the pont", as Animal stated recently, and I am European where words are still used in their true and honest meaning. We are not (yet) raped by political correctness. We die and don't "pass away" (stupid term) and we have "problems" not "issues". Thus, our language lies less, unfortunately not necessarily the speakers.

and i must reiterate: "it is one thing to be forthright. it is quite another to be rude".




Problem 1 is that North Americans have been so extremely brain-washed by PC that this often distorts their reality, problem 2 is that PC is a dictatorial attempt to stop people from thinking and from the truth and the problem 3 is that, as always, North Americans think that their own "standards" are valid for "the rest of world", which is not true and never will be (just like for their insane laws or their idiotic patents system). This is why they are so increasingly popular in other countries with old and great cultures.

i am NOT an American, NEITHER am i a European.
You're entitled to your own opinions on the world at large, but i think i speak for most of the forum users when i say i didn't join this forum to debate political / cultural grievances, but to discuss code and how to get actual work done -- i'd appreciate it if you kept the forum that way for the rest of us.




But all of this was just meant in general, of course, to make you aware of this.

Thank you for that little shiny nugget of information.
Contrary to what you're insinuating though, you're not the only "aware" and enlightened one.

TheBerliner
7 Sep 2009, 10:29 AM
Hello Mystix,

First of all, thank you for your long reply and I hope I can respond accordingly.

Now the technical discussion seems to be clarified and if I understand you correctly, the containers place the labels as they like and they completely neglect the setting of coordinates in the widgets. Again: In my view, this is a wrong concept and I hope (but doubt) that the Ext developers will comprehend that this was a mistake.

Again: In many cases, chaining widgets would be the best solution.


before i respond to the latter half your post, let me state for the record:
i am a forum volunteer, so i'll address only what i can in my capacity as a volunteer

This is what makes me very suspicious, because all the Ext expert people I am talking to here finally disclose that they are forum volunteers! I'm surprised to read this about you, too.

This strengthens my impression that the Ext company has developed a very clever business model with minimal technical documentation (which would be regarded as insufficient by every central European court) and this is obviously compensated by plenty of volunteers. Seems to be a clever and profitable business model!



i'm not requesting that you compose Bach's Air on G String. i'm attempting to address your desire to see the "minimal and frugal" documentation expanded and improved upon.


though there is a commerical side to Ext, the documentation is almost entirely community-driven. which is why i think it completely absurd that a large number of people who complain about the documentation do so without being able to describe the cause of their misery

Once more (and I stated this several times already): if I had seen at least a minimal interest by the Ext company in their user's experiences especially regarding the documentation, I would have made plenty of very valuable comments over the past weeks.

But I did not, simply because I was forced to gain the impression that Ext LLC is absolutely not interested in any user experiences. Several long and detailed e-mails to various people remained completely unanswered.

It is hardly possible to express the lack of interest more precisely than they did!

Thank you for pointing me to these documentation threats, which I had not known before. Although I have been criticising the documentation regularly here, I have neither been pointed to, nor stumbled over these threats. Besides that I don't think they will change much.


you've quite obviously spotted a minefield of mistakes / inadequacies in the documentation, and you definitely qualify as someone who has had an absolutely lousy first-hand experience with the documentation.
Yes, unfortunately you are right!

Well, first of all it is generally regarded as one of the main duties of any product vendor and of software vendors in particular to deliver an adequate documentation. I am sure, this is not only the case in the EU but also in the US and in all other industrialized parts of the world.

Second, I think the idea that "a community" writes a documentation, especially for what is finally a commercial product, is absurd both from the technical as well as from the commercial point of view.

And third, of course I could name many details of why I have found (this is not just a personal opinion in the sense of "regard") the documentation to be absolutely insufficient, but as I wrote before, due to the lack of any interestof Ext LLC I did not make any notes. This only makes sense if you have at least the feeling to be taken seriously. The whole reaction on this forum by all people who claimed to be supporters, support team, or alike, successfully prevented me from getting this positive impression.

As a good example, see the recent threat here (http://www.extjs.com/forum/showthread.php?t=79674), which shows well how a customer is treated when criticising the state of their documentation.

Regarding the rest (language considered rude), I answer to this in a PM in order to keep the forum to discussing code. Neverstheless, I cannot see what is rude about these statements and I fully stand behind them.

Best regards

mono blaine
16 Oct 2009, 6:03 AM
for the time spinner (Ext.ux.form.Spinner.TimeStrategy), validation could be performed this way: (if anyone mentioned this before, sorry about that. i didn't have time to search)


// When you initialize a Spinner object give a regex

var s = new Ext.ux.form.Spinner({
strategy: new Ext.ux.form.Spinner.TimeStrategy(),
regex: /^(([01][0-9])|2[0-3]):[0-5][0-9]$/
});

ZooKeeper
12 Jan 2010, 7:19 AM
There's an issue when spinner is inserted into a column.


items: [{
layout: 'column',
items: [{
layout: 'form',
columnWidth:.65,
labelWidth : 160,
defaults: {
anchor: '90%'
},

http://my.jetscreenshot.com/demo/20100112-pz24-2kb

Bucs
1 Feb 2010, 11:37 AM
I have several spinners controls (number) on a form and want to fire an event to clear the values of the other spinners when a particular spinner is clicked. I cannot seem to figure out which event to process to make this work. 'blur' doesn't work because it doesn't appear the input boxes are selected when the spinner is clicked. 'change' functions very similar to 'blur' only when the value has changed....but again, this won't fire on a new triggerfield's click if the first triggerfield's input was not focused.

So, I need to fire an event on the click event of the trigger I think. Any ideas as to the best way to do this? Tried to listen to 'onTriggerClick' but nothing happened.

Code for one Spinner field:


{
xtype : 'uxspinner',
fieldLabel : 'Cost $',
id : 'Cost',
name : 'cost',
value : 0,
selectOnFocus: true,
strategy: new Ext.ux.form.Spinner.NumberStrategy({
minValue:'0',
maxValue:'100000',
incrementValue: 100,
allowDecimals: true,
decimalPrecision: 2
}),
listeners: {change:{scope: this, fn:function(){
// call event here
}
}}
}Thanks

TheBerliner
1 Feb 2010, 12:33 PM
Well, again the old ongoing documentation problem in Ext. If they had a proper doc you could take your missing information from there.

I had to figure out these details painfully and by wasting a lot of time. Here is one of my declarations of a Spinner button as an example. I generally declare UI elements separately and then add them where needed (versus this rather chaotic form of "inline" declaration that seems to be preferred by most here):


app.ui['buttonToolsGotoPage'] = new Ext.ux.SpinnerField({
name: 'buttonToolsGotoPage',
id: 'buttonToolsGotoPage',
cls: 'csButtonZoomSet',
scale: 'medium',
allowDecimals: false,
minValue: 1,
maxValue: 5,
incrementValue: 1,
alternateIncrementValue: 10,
accelerate: false,
autoWidth: false,
labelWidth: 30,
height: cfg.cfg30330,
width: cfg.cfg30331,
x: 3,
y: cfg.yPosInRowNext() + 5,
strategy: new Ext.ux.Spinner.NumberStrategy({minValue:'1', maxValue:'3'}),
listeners: {blur: entryFieldSpinnerPage,
change: entryFieldSpinnerPage,
spin: entryFieldSpinnerPageSpin} //must be without () stupid!
});It's quite possible that one of the above listener is not needed, but like this it works.

Please note that for some stupid unknown reason that is nowhere explained and completely illogical to me, the methods that are called as listeners must be declared without "()" and also they cannot have arguments, which is often very hindering.

Settings the values of the spinners works like this:


setSpinnerPageTo: function(aPageNr){
var spinnerObj = Ext.getCmp('buttonToolsGotoPage');
//Button objects not yet created during start
if(isNilOrEmpty(spinnerObj)) {return;}
var aMaxValue = this.tabObj.nrOfPages;
//activate row in pagesGrid if visible
men.changeGridPagesToPage(aPageNr);
spinnerObj.maxValue = aMaxValue;
this.privateSetSpinnerTo(spinnerObj,aPageNr);
},And the actual value update is done here:


privateSetSpinnerTo: function(anObj, aValue){
anObj.setValue(aValue);
anObj.show();
},In my case, these spinner buttons can be located in three places and updated from several places in the app.

I hope it helps.

Bucs
1 Feb 2010, 12:45 PM
Thanks Berliner! Just need to know about the "spin" event.

FYI, I generally find the ExtJS documentaiton very helpful, however since this is a comminuty extention, it does not appear in the "sanctioned" documentation.

Thanks again, that did the trick for me :)

Chaoz
8 Feb 2010, 8:07 AM
Hi,

I'm wondering if its possible to link one spinner to another, so one spins up/increase the other decreases in value or spins down?

thanks!

Bucs
8 Feb 2010, 8:14 AM
Hi Chaoz, certainly doable. I would hookup a listener to Spinner 1's "spin" event and then call a function to increase Spinner 2's value using setValue method.



{
xtype : 'uxspinner1',
fieldLabel : 'Spinner 1',
id : 'spinner1',
name : 'Spinner1',
value : 0,
selectOnFocus: true,
strategy: new Ext.ux.form.Spinner.NumberStrategy({
minValue:'0',
maxValue:'100',
incrementValue: 1,
allowDecimals: true,
decimalPrecision: 2
}),
listeners: {spin:{scope: this, fn:function(){
Ext.getCmp('uxspinner2').setValue(some_new_value);
}
}}
}


Hope that helps...

Chaoz
9 Feb 2010, 7:51 AM
Hi Bucs,

Thanks for the tip! It did the trick, though instead of listening to 'spin', I was both listening to 'spinup' and 'spindown'


thanks again!

Bucs
12 Feb 2010, 5:56 AM
Getting some weirdness in a form panel with spinners. The form panel exists in a collapsed east border region, and I have 4 spinners in that form panel. The weirdness is relating to using the "value: 0" on the spinner field to initialize the value. If the "value" property is set in the form config, the collapsed east region holding the form panel with the spinners actually renders expanded first then collapses, even though collapsed is set to true. Removing the "value: 0" eliminates the behavior. Almost as if the value property is forcing a render event to occur, or at least making it expand initially before the container layout forces it to collapse again. Looks ugly so thought I would post.

I know, weird and makes no sense. The workaround is to set the values via a listener on the panel's expand event.

This is a pretty nested layout so almost too much code to post without getting confused...just want to throw the basic issue out there first to see if anyone else has experienced this.

Thanks

Chaoz
12 Mar 2010, 8:27 PM
Hi,
A followup question to my previous post... I wanted the spinner field uneditable, in a way the user is forced to use the spinner and wont be able to type in the numberfield.. now I modified the SpinnerField.js and added a config readOnly: true, but the I got what I wanted BUT now the spinner cannot change the value in the field... I tried a silly hack


Ext.getCmp('qty').setReadOnly( false );
if ( Ext.getCmp('qty').getValue()-1 >= 0 ) {

Ext.getCmp('qty').setValue( Ext.getCmp('qty').getValue()-1 );

}
Ext.getCmp('qty').setReadOnly( true );

but it didnt work

any help would be appreciated

thanks

Chaoz
22 Mar 2010, 4:57 AM
hmm... anyone? still not working for me though :(

Chaoz
8 Apr 2010, 8:12 PM
still no one can ? :(

Christiand
4 Feb 2011, 11:26 AM
modify or override spinner.js

onTriggerClick and isSpinnable function both start with

if (this.disabled || this.el.dom.readOnly) {

change to

if (this.disabled) {