fix(focus-trap): exception when element contains SVG on IE (#3432)

Fixes an exception being thrown by the focus trap, if it contains an SVG element on IE. The problem was that on IE, SVG elements don't have the `children` property, which means that we have to fall back to `childNodes`.

Fixes #3410.
This commit is contained in:
Kristiyan Kostadinov
2017-03-07 01:51:59 +01:00
committed by tinayuangao
parent 842896be3e
commit d06ad753e8
2 changed files with 51 additions and 7 deletions
+35 -1
View File
@@ -9,7 +9,13 @@ describe('FocusTrap', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [FocusTrapDirective, FocusTrapWithBindings, SimpleFocusTrap, FocusTrapTargets],
declarations: [
FocusTrapDirective,
FocusTrapWithBindings,
SimpleFocusTrap,
FocusTrapTargets,
FocusTrapWithSvg
],
providers: [InteractivityChecker, Platform, FocusTrapFactory]
});
@@ -112,6 +118,20 @@ describe('FocusTrap', () => {
expect(document.activeElement.id).toBe('last');
});
});
describe('special cases', () => {
it('should not throw when it has a SVG child', () => {
let fixture = TestBed.createComponent(FocusTrapWithSvg);
fixture.detectChanges();
let focusTrapInstance = fixture.componentInstance.focusTrapDirective.focusTrap;
expect(() => focusTrapInstance.focusFirstTabbableElement()).not.toThrow();
expect(() => focusTrapInstance.focusLastTabbableElement()).not.toThrow();
});
});
});
@@ -156,3 +176,17 @@ class FocusTrapWithBindings {
class FocusTrapTargets {
@ViewChild(FocusTrapDirective) focusTrapDirective: FocusTrapDirective;
}
@Component({
template: `
<div cdkTrapFocus>
<svg xmlns="http://www.w3.org/2000/svg">
<circle cx="100" cy="100" r="100"/>
</svg>
</div>
`
})
class FocusTrapWithSvg {
@ViewChild(FocusTrapDirective) focusTrapDirective: FocusTrapDirective;
}
+16 -6
View File
@@ -128,10 +128,15 @@ export class FocusTrap {
return root;
}
// Iterate in DOM order.
let childCount = root.children.length;
for (let i = 0; i < childCount; i++) {
let tabbableChild = this._getFirstTabbableElement(root.children[i] as HTMLElement);
// Iterate in DOM order. Note that IE doesn't have `children` for SVG so we fall
// back to `childNodes` which includes text nodes, comments etc.
let children = root.children || root.childNodes;
for (let i = 0; i < children.length; i++) {
let tabbableChild = children[i].nodeType === Node.ELEMENT_NODE ?
this._getFirstTabbableElement(children[i] as HTMLElement) :
null;
if (tabbableChild) {
return tabbableChild;
}
@@ -147,8 +152,13 @@ export class FocusTrap {
}
// Iterate in reverse DOM order.
for (let i = root.children.length - 1; i >= 0; i--) {
let tabbableChild = this._getLastTabbableElement(root.children[i] as HTMLElement);
let children = root.children || root.childNodes;
for (let i = children.length - 1; i >= 0; i--) {
let tabbableChild = children[i].nodeType === Node.ELEMENT_NODE ?
this._getLastTabbableElement(children[i] as HTMLElement) :
null;
if (tabbableChild) {
return tabbableChild;
}