PDA

View Full Version : How to properly override and load an existing ExtJs class?



myExtJsUname
9 Nov 2012, 9:14 AM
Hello all,

This is a follow up question to my (sort of "solved") question "Adding tabindex to HTML for Ext.panel.Tool?" thread (http://www.sencha.com/forum/showthread.php?248450-Adding-tabindex-to-HTML-for-Ext.panel.Tool).

To summarize that problem, we are required to ensure all our web application pages meet WCAG 2.0 standards regarding keyboard accessibility (among other things, but for now I'm just talking about that). In particular, this means we need to provide the ability to use a keyboard to tab to an Ext.panel.Tool in a Panel and have an ENTER keypress invoke whatever it is that tool is supposed to do (e.g., close the panel, open the help, collapse/expand the panel, etc.).

In order to effect this functionality, I need to override the Ext.panel.Tool class and I have managed to do so, as follows:


Ext.define(
"Ext.panel.Tool"
,{
override: "Ext.panel.Tool"
,renderTpl: [
'<img id="{id}-toolEl" src="{blank}" class="{baseCls}-{type}" role="presentation" tabindex="0" />'
]
,initComponent: function(){
var me = this;

me.callParent();

me.on(
{
element: "toolEl"
,focus: me.onFocus
,blur: me.onBlur
,scope: me
}
);
}

,afterRender: function(){
var me = this;
me.callParent();

this.getEl().addListener(
"keyup"
,function(evt, target, eOpts){
if (evt.keyCode == evt.ENTER){
this.onClick(evt, target);
}
}
,me
);
}

,onFocus: function(evt){
this.onMouseOver();
}
,onBlur: function(evt){
this.onMouseOut();
}
}
);

My problem now is in figuring out where to put this define so it is loaded into memory at runtime. Until now, I have just slapped it in to the top of the Application's launch() to get it working, but that isn't a final solution because there will likely be many of these that I need to override as I address other WCAG requirements. At the moment, I have a file in my source at /src/core/extjs/panel/Tree.js with this definition in it and in my Ext.Loader config, I can set a path for "Ext" to "/src/code/extjs/" but because I load ext-all-debug.js in my html page, as far as ExtJs is concerned the browser already has a definition for Ext.panel.Tree, so it's not going to go looking for mine...unless there is some way to force it?

If there isn't some way to force it to go and load my Ext.panel.Tree override definition, then there must be some other way to properly override an existing ExtJs class. It should not be a newly named class because then Ext.panel.Panel wouldn't know to use my uniquely named Tool, I'd need to define a new Panel as well that uses my Tools, and then I'd need to define a new Window that uses my Panel, etc., etc. That's way too complicated. I'd be re-defining too many ExtJs classes because this keyboarding to a Tool is only one example of the many WCAG requirements we need to fulfill.

So, I believe my question is this:

How do I properly override and then load the override definition to an existing ExtJs class (not define a new one, but actually override an existing one) in my application? The examples I have seen create new classes (even though they have an "override" property, which I really don't understand).

Or, if I'm on the completely wrong track in how I'm trying to address this (and subsequent similar) requirement(s), some hints towards a better approach would be appreciated.

Cheers,
jtm

skirtle
9 Nov 2012, 1:24 PM
The problem is here:


Ext.define(
"Ext.panel.Tool"
,{
override: "Ext.panel.Tool"

It should be something like this:


Ext.define(
"MyApp.panel.Tool"
,{
override: "Ext.panel.Tool"

The class name should not match the override name. It's important to realise that this does not create a new class, it changes Ext.panel.Tool directly.

You can then require MyApp.panel.Tool just like you would a normal class.

myExtJsUname
9 Nov 2012, 2:04 PM
Wow! I must have missed or didn't understand the significance of something in the docs (which I must admit is typical of me) because never in a million years would I have figured that one out!! This part
It's important to realise that this does not create a new class, it changes Ext.panel.Tool directly. totally escaped me. Doesn't matter...I just tried it and it works fine. Thank you, skirtle, for your quick response to my question.

To finish this off, under my existing "/src/code/extjs/" directory, I now have "/src/code/extjs/override/panel/Tool.js" and it's content is attached below. I also have an Ext.Loader configured with a path for "Ext" pointing to "/src/code/extjs/". This works, in our particular case because we load ext-all.js or ext-all-debug.js to start with so the Loader will only look in our code tree for those "Ext" classes that aren't defined in the ExtJs library (like "Ext.override.panel.Tree" below). Finally, I added this new class as a "requires"-ment to my applications' definitions.

Cheers,
jtm


Ext.define(
"Ext.override.panel.Tool"
,{
override: "Ext.panel.Tool"
,renderTpl: [
'<img id="{id}-toolEl" src="{blank}" class="{baseCls}-{type}" role="presentation" tabindex="0" />'
]
,initComponent: function(){
var me = this;

me.callParent();

me.on(
{
element: "toolEl"
,focus: me.onFocus
,blur: me.onBlur
,scope: me
}
);
}

,afterRender: function(){
var me = this;
me.callParent();

this.getEl().addListener(
"keyup"
,function(evt, target, eOpts){
if (evt.keyCode == evt.ENTER){
this.onClick(evt, target);
}
}
,me
);
}

,onFocus: function(evt){
this.onMouseOver();
}
,onBlur: function(evt){
this.onMouseOut();
}
}
);