/** * @class Ext.tree.NavigationModel * @private * This class listens for key events fired from a {@link Ext.tree.Panel TreePanel}, * and moves the currently focused item by adding the class {@link #focusCls}. * * Navigation and interactions are defined by http://www.w3.org/TR/2013/WD-wai-aria-practices-20130307/#TreeView * or, if there are multiple visible columns, by http://www.w3.org/TR/2013/WD-wai-aria-practices-20130307/#treegrid */Ext.define('Ext.tree.NavigationModel', { extend: 'Ext.grid.NavigationModel', alias: 'view.navigation.tree', initKeyNav: function(view) { var me = this, columns = me.view.ownerGrid.columns; // Must go up to any possible locking assembly to find total number of columns me.isTreeGrid = columns && columns.length > 1; me.callParent([view]); me.view.grid.on({ columnschanged: me.onColumnsChanged, scope: me }); }, onKeyNavCreate: function(keyNav) { var fn = this.onAsterisk; keyNav.map.addBinding([{ key: '8', shift: true, handler: fn, scope: this }, { key: Ext.event.Event.NUM_MULTIPLY, handler: fn, scope: this }]); }, onColumnsChanged: function() { // Must go up to any possible locking assembly to find total number of columns this.isTreeGrid = this.view.ownerGrid.getVisibleColumnManager().getColumns().length > 1; }, onCellClick: function(view, cell, cellIndex, record, row, recordIndex, clickEvent) { this.callParent([view, cell, cellIndex, record, row, recordIndex, clickEvent]); // Return false if node toggled. // Do not process the cell click further when we do an expand/collapse return !clickEvent.nodeToggled; }, onKeyLeft: function(keyEvent) { var me = this, view = keyEvent.view, record = me.record; // Left when a TreeGrid navigates between columns if (me.isTreeGrid && !keyEvent.ctrlKey) { return me.callParent([keyEvent]); } // Left arrow key on an expanded node closes the node. if (keyEvent.position.column.isTreeColumn && record.isExpanded()) { view.collapse(record); } // Left arrow key on a closed or end node moves focus to the node's parent // (don't attempt to focus hidden root). else { record = record.parentNode; if (record && !(record.isRoot() && !view.rootVisible)) { me.setPosition(record, null, keyEvent); } } }, onKeyRight: function(keyEvent) { var me = this, record = me.record; // Right when a TreeGrid navigates between columns if (me.isTreeGrid && !keyEvent.ctrlKey) { return me.callParent([keyEvent]); } // Right arrow key expands a closed node, moves to the first child of an open node, // or does nothing on an end node. if (!record.isLeaf()) { if (keyEvent.position.column.isTreeColumn && !record.isExpanded()) { keyEvent.view.expand(record); } else if (record.isExpanded()) { record = record.childNodes[0]; if (record) { me.setPosition(record); } } } }, onKeyEnter: function(keyEvent) { if (this.record.data.checked != null) { this.toggleCheck(keyEvent); } else { this.callParent([keyEvent]); } }, onKeySpace: function(keyEvent) { if (this.record.data.checked != null) { this.toggleCheck(keyEvent); } else { this.callParent([keyEvent]); } }, toggleCheck: function(keyEvent) { this.view.onCheckChange(keyEvent); }, // (asterisk) on keypad expands all nodes. onAsterisk: function(keyEvent) { this.view.ownerGrid.expandAll(); }});