PDA

View Full Version : Keyboard Events for Ext.BoxComponent



v.madhu
2 Jul 2010, 3:28 AM
Hello,
I wrote a component extending Ext.BoxComponent
I added mouse listeners it is working fine. But keypress listeners are not working.
Probably i did mistake the way i create events. Below is the sample source.

onRender : function(ct, position){

this.el = ct.createChild({
tag: 'div',
id: Ext.id(),
children: this.starsDom
});


this.el.on({
scope : this,
click: this.onStarClick,
mouseover: this.onStarOver,
mouseout: this.onStarOut,
keypress: this.keyPress,
keydown: this.keyDown
});

}

Please comment.

Thanks.

Condor
2 Jul 2010, 4:04 AM
The browser only accepts key events on elements that can have the focus.

On most browsers you can do this by giving the element a tabIndex, but on IE6 the only safe way is to use an <a> element.

v.madhu
2 Jul 2010, 5:27 AM
Can you please provide an example?

Condor
2 Jul 2010, 5:35 AM
Simply change tag:'div' to tag:'a'.

(you'll probably want to stop any click event on the <a> element though)

v.madhu
2 Jul 2010, 6:06 AM
I tried it. It is not working. Thats probably because i am using this component inside grid. Basically the Starrating component (extends BoxComponent) which is inside LockingEditorGridPanel.

The basic problem is keyediting is not supported by this component, also i attached blur event to this component, the event is not fireing.

The scnario is when the starrating cell is in editable mode and when i click outside the LockingEditorGridPanel, the starrating cell is still in editable mode. When i tried the same for TextField editable cell, it is working perfectly.

Please suggest what i can do to fix this.

Condor
2 Jul 2010, 6:12 AM
You do NOT want to use components inside a grid (they leak memory if you are not VERY careful)!

Instead, you should create a renderer that renders the current star rating and a separate editor that descends Ext.form.Field and not from Ext.BoxComponent that allows editing the rating.

v.madhu
2 Jul 2010, 6:14 AM
One more info is, After editing the starrating if i click next cell the value is getting stored in the store. So what i am trying to do is
1) when the starrating is in editable mode and when i click anywhere outside the grid, the current value must be stored in the store.
2) I want to add keyevent to it.

Both are not working.

v.madhu
5 Jul 2010, 1:24 AM
Hi Condor,

As per your suggesion, I extended the Starrating component by Ext.form.Field.
Now i can see the keyevents working. But still i am facing focus out issue. I mean
once the editor is started and values are edited, when i hit tab, the changed value is not
updating in the store. But it is working when i do the same thru mouse. That is after changing
the value if i click any column in the grid, the changed value is stored in the store.

I guess the problem is with the onRender function. Here is the code.


onRender : function(ct, position){
Ext.form.StarRating.superclass.onRender.call(this, ct, position);

if(this.value!=''){
for(var i=1;i<this.starsConfig.length;i++){
this.starsDom[i].cls='ux-rating-star ux-rating-star-on';
if(this.starsConfig[i].value==this.value){
break;
}
}
}

this.el.remove();
this.el = ct.createChild({
tag: 'div',
id: Ext.id(),
cls : 'ux-rating-container ux-rating-clearfix',
children: this.starsDom
});


this.el.on({
scope : this,
click: this.onStarClick,
mouseover: this.onStarOver,
mouseout: this.onStarOut

});

this.autoEl = this.el;
},

And initComponent function is


initComponent : function(config){
console.log('initComponent')

Ext.form.StarRating.superclass.initComponent.call(this);
Ext.apply(this, config);
this.starsDom = new Array();

resetVisible = ' display:block;';
if(this.disabled || this.requiredRating){
resetVisible = ' display:none;';
}

this.starsDom.push({tag:'div', cls:'ux-rating-reset ' , style :'width: 16px;'+ resetVisible ,
children:[ {tag:'a', title:this.starsConfig[0].toolTip, style:'margin-left: 0px;', html: ''}] });

for(var i=1;i<this.starsConfig.length;i++){
var starObject = {tag:'div', cls:'ux-rating-star ' , style :'width: 16px;',
children:[ {tag:'a', title:this.starsConfig[i].toolTip, style:'margin-left: 0px;',
html: this.starsConfig[i].value}] };
this.starsDom.push(starObject);
}
this.addEvents(
'keydown',
'keyup',
'keypress'
);
},

Please comment.

v.madhu
5 Jul 2010, 4:04 AM
Anyone please respond!

v.madhu
6 Jul 2010, 2:32 AM
Anyone?

Condor
6 Jul 2010, 3:45 AM
You're not correctly basing the component on an Ext.form.Field. It should implement all Ext.form.Field features, including a blur event.

v.madhu
12 Jul 2010, 1:55 AM
Can you please be more specific?

Condor
12 Jul 2010, 2:11 AM
Being more specific would almost require building the entire component myself.

Maybe you can look at how some other Ext.form.Field descendants do this (e.g. SliderField).

v.madhu
13 Jul 2010, 3:40 AM
Hi Condor, As per your suggestion i modified the component. Now the tabbing out problem is solved. But i am facing one problem. Once the cell is start edited, and i am changing any value (by clicking stars) Now i am clicking away from the grid. Here the editor is still in editable mode. It is not focusing out. Here is the source. Please help.



Ext.StarRatingComponent = Ext.extend(Ext.BoxComponent, {

value: '',
starsDom : new Array(),
disabled : false,
starsConfig:new Array(),
requiredRating : false,


// private
initComponent : function(){
Ext.StarRatingComponent.superclass.initComponent.call(this);
this.starsDom = new Array();
resetVisible = ' display:block;';
if(this.disabled || this.requiredRating){
resetVisible = ' display:none;';
}

this.starsDom.push({tag:'div', cls:'ux-rating-reset ' , style :'width: 16px;'+ resetVisible ,children:[ {tag:'a', title:this.starsConfig[0].toolTip, style:'margin-left: 0px;', html: ''}]});

for(var i=1;i<this.starsConfig.length;i++){
var starObject = {tag:'div', cls:'ux-rating-star ' , style :'width: 16px;',children:[ {tag:'a', title:this.starsConfig[i].toolTip, style:'margin-left: 0px;', html: this.starsConfig[i].value}]};
this.starsDom.push(starObject);
}
this.addEvents(
'change'
);

},

// private
onRender : function(ct, position){

if(!this.el){

if(this.value!=''){
for(var i=1;i<this.starsConfig.length;i++){
this.starsDom[i].cls='ux-rating-star ux-rating-star-on';
if(this.starsConfig[i].value==this.value){
break;
}
}
}

this.el = ct.createChild({
tag: 'div',
id: Ext.id(),
cls : 'ux-rating-container ux-rating-clearfix',
children: this.starsDom
});


this.el.on({
scope : this,
click: this.onStarClick,
mouseover: this.onStarOver,
mouseout: this.onStarOut

});

this.autoEl = this.el;
}


Ext.StarRatingComponent.superclass.onRender.call(this, ct, position);

},

select : function(value) {

if(value){
this.value=value;
}

if(this.el){
var x = this.el.dom.childNodes;

var lastIndex = 0;
for(var i=1;i<this.starsConfig.length;i++){
x[i].className= 'ux-rating-star ux-rating-star-on';
if(this.starsConfig[i].value==this.value){
lastIndex = i;
break;
}
}
for(var i=lastIndex+1;i<this.starsConfig.length;i++){
x[i].className='ux-rating-star ';
}

}

},

onStarClick : function(ev, t) {
if(this.disabled)return;
/* Workaround to stop the fireEvent when the user clicks on the container of the stars */
if(t.innerHTML.indexOf('class') != -1) {
return;
}
try {
this.value = t.innerHTML;
var x = this.el.dom.childNodes;

if(this.value==''){
x[0].className= 'ux-rating-reset'; //reset
for(var i=1;i<this.starsConfig.length;i++){
x[i].className='ux-rating-star ';
}
}else{
var lastIndex = 0;
for(var i=1;i<this.starsConfig.length;i++){
x[i].className= 'ux-rating-star ux-rating-star-on';
if(this.starsConfig[i].value==this.value){
lastIndex = i;
break;
}
}
for(var i=lastIndex+1;i<this.starsConfig.length;i++){
x[i].className='ux-rating-star ';
}
}
this.fireEvent('change',this.value);
}catch(e){
// Ignore errros
}

},

onStarOver : function(ev, t) {

if(this.disabled)return;

var elementHover = -1;
try{

elementHover = t.innerHTML;
var x = this.el.dom.childNodes;

if(elementHover=='' || elementHover==undefined){ // reset
x[0].className= 'ux-rating-reset ux-rating-reset-hover';
}else{

var lastIndex = 0;
for(var i=1;i<this.starsConfig.length;i++){
x[i].className= 'ux-rating-star ux-rating-star-hover';
if(this.starsConfig[i].value==elementHover){
lastIndex = i;
break;
}
}
for(var i=lastIndex+1;i<this.starsConfig.length;i++){
x[i].className='ux-rating-star ';
}
if(lastIndex==0 && this.value!=null && this.value!=''){
for(var i=1;i<this.starsConfig.length;i++){
x[i].className= 'ux-rating-star ux-rating-star-on';
if(this.starsConfig[i].value==this.value){
break;
}
}
}

}

}catch(e){}

},

onStarOut : function(ev, t) {

if(this.disabled)return;
var divElement = t.parentNode.parentNode;
// elementHover = eval(t.innerHTML);


if(divElement.className.indexOf('ux-rating-container') != -1){
var x = this.el.dom.childNodes;

x[0].className= 'ux-rating-reset'; //reset

var lastIndex = 0;
for(var i=1;i<this.starsConfig.length;i++){
x[i].className= 'ux-rating-star ux-rating-star-on';
if(this.starsConfig[i].value==this.value){
lastIndex = i;
break;
}
}
for(var i=lastIndex+1;i<this.starsConfig.length;i++){
x[i].className='ux-rating-star ';
}

}
},

setValue : function(v){
this.value = v;
},

getValue : function(){
return this.value;
},

isValid : function(preventMark){
return true;
},

reset : function() {
}

});
Ext.reg('starratingComponent', Ext.StarRatingComponent);

and


Ext.form.StarRating = Ext.extend(Ext.form.Field, {

initComponent : function() {
this.starrating = new Ext.StarRatingComponent(this.initialConfig);
Ext.form.StarRating.superclass.initComponent.call(this);
this.addEvents( 'blur' );

},
initEvents : function(){

Ext.form.StarRating.superclass.initEvents.call(this);

this.mon(this.starrating, 'blur', this.onBlur, this, this.inEditor ? {buffer:10} : null);
},


onBlur : function(){
this.fireEvent('blur', this);
},

onRender : function(ct, position){
this.autoCreate = {
id: this.id,
name: this.name,
type: 'hidden',
tag: 'input'
};

Ext.form.StarRating.superclass.onRender.call(this, ct, position);
console.log('setting tabindex ');
this.wrap = this.el.wrap({});
this.wrap.dom.setAttribute('tabIndex', '0');
this.forcusEL = this.resizeEl = this.positionEl = this.wrap;
this.starrating.render(this.wrap);

},

setValue : function(v){
this.starrating.setValue(v);
return Ext.form.StarRating.superclass.setValue.call(this, this.starrating.getValue());
},

getValue : function(){
return this.starrating.getValue();
},

beforeDestroy : function(){
Ext.form.StarRating.superclass.beforeDestroy.call(this);
},

onEnable : function(){
Ext.form.StarRating.superclass.onEnable.call(this);

},

onDisable : function(){
Ext.form.StarRating.superclass.onDisable.call(this);

}

});

Ext.reg('starrating', Ext.form.StarRating);