Skip to content

Commit

Permalink
limit tabbing to top modal
Browse files Browse the repository at this point in the history
this limits tab navigation using the same basic approach bootstrap 3
uses, but with no bootstrap. To work perfectly, elements should have
tabindex defined. If not, you may get the address bar included in your
tab cycle. Works in Chrome, FF, IE8 & 9. Did not test 10. No tests
yet...
  • Loading branch information
jmwolfe committed Sep 22, 2013
1 parent 5723a9e commit 759cddb
Showing 1 changed file with 57 additions and 0 deletions.
57 changes: 57 additions & 0 deletions src/modal/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,45 @@ angular.module('ui.bootstrap.modal', [])
modalWindow.modalScope.$destroy();
}

// rough implementation of jquery .has()
function modalContainsElement(modal, element) {
var isChild = false;

var curElement = element;
while (curElement && curElement.localName !== 'html') {
if (curElement === modal.value.modalDomEl[0]) {
isChild = true;
}
curElement = curElement.parentElement;
}
return isChild;
}

// recursively search the DOM tree to find the first input or TEXTAREA type element so we can focus on it.
// you can uncomment the console calls in Chrome to see a nicely indented trace.
function firstInputOf(domEl, level) {
var firstInput = null;
//console.group('Level ' + level);
for (var i = 0; i < domEl.children.length; i++) {
var child = domEl.children[i];
//console.log('Level ' + level + ' Child #' + i + ': ' + child.tagName + ', ' + child.className);
//console.log();
if (child.children.length > 0) { // this child has potential, look for a field
firstInput = firstInputOf(child, level + 1);
}
if (firstInput !== null) {
break; // bubble any recursive results right up
}
if ((child.tagName == 'INPUT' || child.tagName == 'TEXTAREA') && !child.hidden) {
firstInput = child; // found it
break;
}
}
//console.log(firstInput ? 'FOUND IT: ' + firstInput.className : 'DID NOT FIND IT');
//console.groupEnd();
return firstInput; // no children returned anything
}

$document.bind('keydown', function (evt) {
var modal;

Expand Down Expand Up @@ -175,6 +214,24 @@ angular.module('ui.bootstrap.modal', [])
var modalDomEl = $compile(angularDomEl)(modal.scope);
openedWindows.top().value.modalDomEl = modalDomEl;
body.append(modalDomEl);

// unfortunately, not using jquery so we will wipe out existing focusin handlers, not just ours.
// Needed to stop handler creep.
$document.unbind('focusin');

$document.bind('focusin', function (evt) {
var win;
// have to get this fresh because modalDomEl is just at template if you get it at function def
win = openedWindows.top();

var elementAboutToReceiveFocus = evt.target;
if (!modalContainsElement(win, elementAboutToReceiveFocus)) {
var firstInput = firstInputOf(win.value.modalDomEl[0], 0);
if (firstInput !== elementAboutToReceiveFocus && firstInput !== null) {
firstInput.focus();
}
}
});

if (backdropIndex() >= 0 && !backdropDomEl) {
backdropjqLiteEl = angular.element('<div modal-backdrop></div>');
Expand Down

0 comments on commit 759cddb

Please sign in to comment.