(function() { Ext.a11y.ARIA = Ext.apply(new Ext.util.Observable(), function() { return { setRole : function(el, role) { el = Ext.getDom(el); if(el) { el.setAttribute('role', role.toString()); } }, setProperty : function(el, key, value) { el = Ext.getDom(el); if(el) { el.setAttribute(key.toString(), value.toString()); } } } }()); var ARIA = Ext.a11y.ARIA; Ext.override(Ext.tree.TreeNode, { render : function(bulkRender){ this.ui.render(bulkRender); if(!this.rendered){ // make sure it is registered this.getOwnerTree().registerNode(this); this.rendered = true; this.fireEvent('noderender', this); if(this.expanded){ this.expanded = false; this.expand(false, false); } } } }); Ext.override(Ext.tree.TreePanel, { initARIA : function() { Ext.tree.TreePanel.superclass.initARIA.call(this); this.getSelectionModel().on('selectionchange', this.onNodeSelect, this); this.ariaTreeEl = this.body.down('.x-tree-root-ct'); this.on('collapsenode', this.onNodeCollapse, this); this.on('expandnode', this.onNodeExpand, this); }, // private registerNode : function(node){ if(this.nodeHash[node.id] === undefined) { node.on('noderender', this.onNodeRender, this); } this.nodeHash[node.id] = node; }, // private unregisterNode : function(node){ node.un('noderender', this.onNodeRender, this); delete this.nodeHash[node.id]; }, onNodeRender : function(node) { var a = node.ui.anchor, level = this.rootVisible ? 1 : 0, pnode = node; if(node.isRoot) { ARIA.setRole(this.ariaTreeEl, 'tree'); ARIA.setProperty(this.ariaTreeEl, 'aria-labelledby', Ext.id(node.ui.textNode)); ARIA.setProperty(this.ariaTreeEl, 'aria-activedescendant', 'false'); if(!this.rootVisible) { return; } } ARIA.setRole(node.ui.wrap, 'treeitem'); ARIA.setProperty(node.ui.wrap, 'aria-labelledby', Ext.id(node.ui.textNode)); ARIA.setProperty(node.ui.wrap, 'aria-expanded', 'false'); ARIA.setProperty(node.ui.wrap, 'aria-selected', 'false'); while (pnode.parentNode) { level++; pnode = pnode.parentNode; } ARIA.setProperty(node.ui.wrap, 'aria-level', level); if(!node.isLeaf()) { ARIA.setRole(node.ui.ctNode, 'group'); ARIA.setProperty(node.ui.wrap, 'aria-expanded', node.isExpanded()); } }, onNodeSelect : function(sm, node) { ARIA.setProperty(this.ariaTreeEl, 'aria-activedescendant', Ext.id(node.ui.wrap)); ARIA.setProperty(node.ui.wrap, 'aria-selected', 'true'); }, onNodeCollapse : function(node) { ARIA.setProperty(node.ui.wrap, 'aria-expanded', 'false'); }, onNodeExpand : function(node) { ARIA.setProperty(node.ui.wrap, 'aria-expanded', 'true'); } }); })();