PDA

View Full Version : Suggetions for accessing elements without IDs with DOM query?



JimR
5 Jan 2011, 11:18 PM
We are adding WAI-ARIA states to EXT JS 3.3 code via direct updating of the DOM. In many cases this is simple because EXT JS allows assigning an ID to the component at the approrpiate level of granularity. For example:

document.getElementById('searchResultsTabPanel').setAttribute("role","tabpanel");

However, in many cases, the level at which an ID can be assigned is fairly far from the HTML tag we need to update. For example, when you use a table layout to create a form, there is a lot of "fluff" before you actually get down to the table:

<div id="expertSearch1" class=" x-panel x-panel-noborder" style="vertical-align: top; width: 1198px;" role="search">
<div class="x-panel-header x-panel-header-noborder x-unselectable" id="ext-gen30" style="-moz-user-select: none;">
<div class="x-tool x-tool-toggle" id="ext-gen33">&nbsp;</div><span class="x-panel-header-text" id="ext-gen34">Expert Search</span></div>
<div class="x-panel-bwrap" id="ext-gen31">
<div class="x-panel-body x-panel-body-noborder x-table-layout-ct" id="ext-gen32" style="padding: 4px; height: auto; width: 1190px;">

<table cellspacing="0" class="x-table-layout" id="ext-gen193">
[lots of stuff deleted here - this is the actual table info]
</table>

</div>
</div>
</div>
</div>
</div>

So, while we are able to assign an ID ("expertSearch1" in this case) to this component, that does not result in a deterministic ID on the table. This is just one example. Every example is different. Sure, we can greate a DOM query that says, for this particular issue, "Find the div with the ID expertSearch1, then find a child element of that div which is a table, and add this attribute."

But, that's a little brittle, and has to be done through examination of the generated HTML on a case by case basis. Not fun or scalable or maintainable. I know we could extend the objects themselves to use a different HTML template and put IDs in extra places. I went down the DOM road because that's how the single ARIA example Sencha has up (ARIA.js) works, and because it initially seemed easy -- until I realized how many things can't have IDs assigned to them at the right place in the HTML.

Any suggestions? Maybe I'm missing a more elegant way to define elements using ext.dom or pure JS, or maybe extending the objects is the way to go, but since different objects render differently (which will be fixed in 4.0!), with no standard way to change their HTML, that seems ugly too.

Condor
6 Jan 2011, 1:08 AM
I would integrate this into the component, e.g.


{
xtype: 'panel',
id: 'expertSearch1',
layout: 'table',
...
listeners: {
render: function(panel) {
panel.getEl().set('role', 'search');
Ext.fly(panel.getLayout().table).set('role', 'table');
}
}
}

msmolyak
13 Jan 2011, 11:45 AM
Condor,

Could you, please, explain the snippet you posted? The goal here is to add role attributes to some HTML components rendered by ExtJS.

It looks like the snippet defines a listener property with a render() method on the panel. Will this render method be automatically called when the component is created? Is this a standard way to override the render() method on Ext components? Does it have to call the render() method of Ext.Panel or will it happen automatically?

What is panel.getLayout().table? Is this the reference to an HTML table used in the table layout?

One other question. If my classes are defined in the Ext Designer and I do not have direct access to the code that you propose to modify, but can extent the class instead. How would achieve the same effect in the class extending the component defined in the designer?

Thank you,

Michael

Condor
13 Jan 2011, 11:46 PM
1. The render event is fired when the component has been rendered to the DOM, so you can use it to modify the created DOM. If you were extending the component you would override the onRender or afterRender method instead.

2. Yes, panel.getLayout().table is a reference to the <table> element created by a table layout.

3. The designer creates 2 classes, a Xxx class and a XxxUi class. You can add the render event handler in the XxxUi class or extend the onRender of afterRender method.
Yet another method (and the one I would recommend) is to override the baseclass (e.g. Ext.Panel) so you don't have to assign roles in every class you create.