键盘导航 Keyboard NavigationNavigating with your keyboard is often faster than using the cursor and is useful for both power users and to provide accessibility to users that find a mouse difficult to use. We're going to convert a modified version of the relatively complicated Ext JS complex layout example into an application that is fully accessible through the keyboard. We'll also add keyboard shortcuts to potentially make navigation via the keyboard faster than the cursor. By the end of this guide you will have an understanding of where keyboard navigation is most needed and how to utilize keyboard navigation with KeyNav, KeyMap and the FocusManager. Getting StartedThese are the files we'll be starting from. Unzip them and open complex.html and complex.js in your preferred editor. Also unzip a copy of Ext JS 4 into the same directory and rename it 'ext'. The Focus ManagerThe Focus Manager provides a very quick way to enable basic keyboard navigation. What's more, it's simple to implement: Ext.FocusManager.enable(true); Write this line inside Ext.onReady; we pass the Boolean Experiment with navigating around the elements solely with the FocusManager. If you can, turn off your mouse too. Although adequate, you'll probably find that certain areas are either inaccessible (such as the grid) or it's quite cumbersome to get around the screen. We're going to tackle this with 'shortcuts' which will allow users to jump to certain panels of the application with ease. When deciding which panels should have shortcuts to them it's useful to have some criteria to go by:
If the answer is yes to at least one of these, give it a keyboard shortcut and aid your end-users. KeyNavIt's the job of KeyNav to provide easy keyboard navigation. It allows you to use the following keys to navigate through your Ext JS application:
It's also worth keeping in mind users with limited keyboards that might not have certain keys, for example certain Apple computers don't have Page Up, Page Down, Del, Home or End keys. Let's take a look at an example of how you'd use it.
var nav = Ext.create('Ext.util.KeyNav', "my-element", {
"left" : function(e){
this.moveLeft(e.ctrlKey);
},
"right" : function(e){
this.moveRight(e.ctrlKey);
},
"enter" : function(e){
this.save();
},
scope : this
});
KeyNav's speciality is listening for arrow keys, so we're going to add the ability to navigate around panels with the arrow keys instead of having to use tab, enter and escape.
var nav = Ext.create('Ext.util.KeyNav', Ext.getBody(), {
"left" : function(){
var el = Ext.FocusManager.focusedCmp;
if (el.previousSibling()) el.previousSibling().focus();
},
"right" : function(){
var el = Ext.FocusManager.focusedCmp;
if (el.nextSibling()) el.nextSibling().focus();
},
"up" : function() {
var el = Ext.FocusManager.focusedCmp;
if (el.up()) el.up().focus();
},
"down" : function() {
var el = Ext.FocusManager.focusedCmp;
if (el.items) el.items.items[0].focus();
},
scope : this
});
We get the currently focused component with focusedCmp. If the function has a value other than KeyMapYou'll notice that there are many regions to our Ext application: North, South, East, and West. We're going to create a KeyMap that will not only focus on these elements but, if the region is collapsed, expand it too. Let's have a look at what a typical KeyMap object looks like.
var map = Ext.create('Ext.util.KeyMap', "my-element", {
key: 13, // or Ext.EventObject.ENTER
ctrl: true,
shift: false,
fn: myHandler,
scope: myObject
});
The first property,
We'll start by concentrating on the main panels: north, south, east and west.
var map = Ext.create('Ext.util.KeyMap', Ext.getBody(), [
{
key: Ext.EventObject.E, // E for east
shift: true,
ctrl: false, // explicitly set as false to avoid collisions
fn: function() {
var parentPanel = eastPanel;
expand(parentPanel);
}
},
{
key: Ext.EventObject.W, // W for west
shift: true,
ctrl: false,
fn: function() {
var parentPanel = westPanel;
expand(parentPanel);
}
},
{
key: Ext.EventObject.S, // S for south
shift: true,
ctrl: false,
fn: function() {
var parentPanel = southPanel;
expand(parentPanel);
}
}
]);
We use Ext.EventObject.X to make it obvious which key we're listening for, the rest should be clear from the example above. Then we write the
function expand(parentPanel) {
parentPanel.toggleCollapse();
parentPanel.on('expand', function(){
parentPanel.el.focus();
});
parentPanel.on('collapse', function(){
viewport.el.focus();
});
}
This function toggles the collapsing of the panel and focuses on it if it's been expanded, or collapses it if it's already expanded, returning focus to the next level up, the Now that all of the code is in place, try expanding and collapsing the panels with a key press versus clicking on the small button that expands or collapses them. It's much faster with the keyboard! Next, we'll go through a similar process with the Navigation, Settings and Information tabs on the West Panel. I've called them subPanels because they're children to the other
{
key: Ext.EventObject.S, // S for settings
ctrl: true,
fn: function() {
var parentPanel = westPanel;
var subPanel = settings;
expand(parentPanel, subPanel);
}
},
{
key: Ext.EventObject.I, // I for information
ctrl: true,
fn: function() {
var parentPanel = westPanel;
var subPanel = information;
expand(parentPanel, subPanel);
}
},
{
key: Ext.EventObject.N, // N for navigation
ctrl: true,
fn: function(){
var parentPanel = westPanel;
var subPanel = navigation;
expand(parentPanel, subPanel);
}
}
We follow the same pattern as we've used before but added a variable called
function expand(parentPanel, subPanel) {
if (subPanel) {
function subPanelExpand(subPanel) {
// set listener for expand function
subPanel.on('expand', function() {
setTimeout(function() { subPanel.focus(); }, 200);
});
// expand the subPanel
subPanel.expand();
}
if (parentPanel.collapsed) {
// enclosing panel is collapsed, open it
parentPanel.expand();
subPanelExpand(subPanel);
}
else if (!subPanel.collapsed) {
// subPanel is open and just needs focusing
subPanel.focus();
}
else {
// parentPanel isn't collapsed but subPanel is
subPanelExpand(subPanel);
}
}
else {
// no subPanel detected
parentPanel.toggleCollapse();
parentPanel.on('expand', function(){
parentPanel.el.focus();
});
parentPanel.on('collapse', function(){
viewport.el.focus();
});
}
}
Despite At this point you can open and close panels, as well as focus them, purely with the keyboard (e.g. shift+e or ctrl+s). Naturally, any function of Ext JS can be triggered by a key press leading to many possibilities for a more native-feeling application. There's one last object to add to our
{
key: Ext.EventObject.W, // W to close
ctrl: true,
fn: function(){
var el = Ext.FocusManager.focusedCmp;
if (el.xtype === 'tab' && el.closable) {
el.up().focus();
el.destroy();
}
},
scope: this
}
We've configured which key presses we're listening for and get which component is currently focused with the Focus Manager's focusedCmp property. If the currently focused component is a tab and it's closable, then we set the focus to the parent panel and destroy the tab. Fixing the GridYou may have noticed that when we try to focus a row in the grid it isn't possible without the mouse. If you look in the console we get a clue as to why this is, it reports that "pos is undefined". The click event passes information on the record, including what its position in the grid is. However, using the FocusManager, it doesn't pass this information so we need to emulate it by passing an object that specifies the
var easttab = Ext.getCmp('easttab');
var gridMap = Ext.create('Ext.util.KeyMap', 'eastPanel', [
{
key: '\r', // Return key
fn: function() {
easttab.getSelectionModel().setCurrentPosition({row: 0, column: 1});
},
scope: 'eastPanel'
},
{
key: Ext.EventObject.ESC,
fn: function() {
easttab.el.focus();
},
scope: 'eastPanel'
}
]);
Try this and you'll see that we can successfully enter and exit the grid using the keyboard. It's important that we specify the Toggling Keyboard MappingA useful feature of If you wanted to add a global key press that would turn on and off keyboard navigation you could do so with the following:
var initMap = Ext.create('Ext.util.KeyMap', Ext.getBody(), {
key: Ext.EventObject.T, // T for toggle
shift: true,
fn: function(){
map.enabled ? map.disable() : map.enable();
Ext.FocusManager.enabled ? Ext.FocusManager.disable() : Ext.FocusManager.enable(true);
}
});
We've created a new ConclusionWe've converted a complex series of panels that would have otherwise been inaccessible to use the keyboard. We've also encountered some examples where we've had to add some custom functionality on top of the Focus Manager. With |
ExtJS 4 指南Ext Core手册资料快速下载
概技术普及,始能进步。稍有累积,颇愿意与大家分享。
本站内容无论翻译或非翻译,除绝少声明转载的外,大多均属原创。 转载时请注明本页信息及“Ext中文网 ajaxjs.com”。转载内容请遵循 Creative Commons 署名-非商业性使用 2.5 方可。
|