Hi,
I am using a lot of Modal windows and dialogs and faced this problem. So here's a solution that I am happy with it for the moment. It may be for somebody out there or for Ext team. By the way this solution work for any HTML container element (div, form, etc) that we don't want the focus to out of it. So it work with any kind of window or panel, etc.
The main idea is to track focusable elements outside our container (window) and return back the focus to our window or any element into it.
Of course this can be optimized.
Here is the code:
Code:
// some utilities:
function registerEvent(elem_, eventName_, handler_) {
if (elem_.attachEvent) {
elem_.attachEvent("on" + eventName_, handler_);
} else if (elem_.addEventListener) {
elem_.addEventListener(eventName_, handler_, true);
}
}
function unregisterEvent(elem_, eventName_, handler_) {
if (elem_.detachEvent) {
elem_.detachEvent("on" + eventName_, handler_);
} else if (elem_.removeEventListener) {
elem_.removeEventListener(eventName_, handler_, true);
}
}
var FOCUSABLES = ',a,input,button,submit,'; // personalize focusable HTML elements
function findFocusable(node_, path_, stopElemId_, result_) {
if (!node_) {
return;
}
if (node_.id && stopElemId_ && node_.id == stopElemId_) {
trace('findFocusable(): stopped at node id=' +stopElemId_);
return;
}
if (!path_) {
path_ = '';
}
var name = node_.nodeName.toLowerCase();
path_ += "/" +name;
if (FOCUSABLES.indexOf(','+name+',') > -1) {
if (!result_[node_]) {
node_._path = path_;
result_[node_] = node_;
}
}
if (node_.childNodes) {
var nodes = node_.childNodes;
for (var i = 0; i < nodes.length; i++) {
findFocusable(nodes[i], path_, stopElemId_, result_);
}
}
}
After creating a window or a panel, etc:
Code:
var win = new Ext.Window({id:<an id>, ...});
win._hasFocusedOutOfWindow = function(event_) {
trace('Left modal window! Back off.');
win.focus(); // require having a default button. we can focus something into the window!
}
win._map = {};
win.on('activate', function() {
findFocusable(document.body, null, win.id, win._map);
for (key in win._map) {
var node = win._map[key];
trace('set listener on focusable element=' +node._path +'#' +node.id);
registerEvent(node, "focus", win._hasFocusedOutOfWindow);
}
});
win.on('deactivate', function() {
for (key in win._map) {
var node = win._map[key];
trace('removed listener on focusable element=' +node._path +'#' +node.id);
unregisterEvent(node, "focus", win._hasFocusedOutOfWindow);
}
});
Hope this will help.
Thanks