@angular/cdk 7.0.4 → 7.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/_a11y.scss +1 -1
- package/a11y/typings/focus-monitor/focus-monitor.d.ts +20 -5
- package/a11y/typings/focus-trap/focus-trap.d.ts +2 -0
- package/a11y/typings/index.metadata.json +1 -1
- package/a11y/typings/live-announcer/live-announcer.d.ts +34 -3
- package/bundles/cdk-a11y.umd.js +477 -216
- package/bundles/cdk-a11y.umd.js.map +1 -1
- package/bundles/cdk-a11y.umd.min.js +1 -1
- package/bundles/cdk-a11y.umd.min.js.map +1 -1
- package/bundles/cdk-accordion.umd.js +16 -9
- package/bundles/cdk-accordion.umd.js.map +1 -1
- package/bundles/cdk-accordion.umd.min.js.map +1 -1
- package/bundles/cdk-bidi.umd.js +11 -6
- package/bundles/cdk-bidi.umd.js.map +1 -1
- package/bundles/cdk-bidi.umd.min.js.map +1 -1
- package/bundles/cdk-coercion.umd.js +25 -9
- package/bundles/cdk-coercion.umd.js.map +1 -1
- package/bundles/cdk-coercion.umd.min.js +1 -1
- package/bundles/cdk-coercion.umd.min.js.map +1 -1
- package/bundles/cdk-collections.umd.js +28 -5
- package/bundles/cdk-collections.umd.js.map +1 -1
- package/bundles/cdk-collections.umd.min.js.map +1 -1
- package/bundles/cdk-drag-drop.umd.js +2177 -915
- package/bundles/cdk-drag-drop.umd.js.map +1 -1
- package/bundles/cdk-drag-drop.umd.min.js +2 -1
- package/bundles/cdk-drag-drop.umd.min.js.map +1 -1
- package/bundles/cdk-keycodes.umd.js +33 -1
- package/bundles/cdk-keycodes.umd.js.map +1 -1
- package/bundles/cdk-keycodes.umd.min.js +1 -1
- package/bundles/cdk-keycodes.umd.min.js.map +1 -1
- package/bundles/cdk-layout.umd.js +29 -22
- package/bundles/cdk-layout.umd.js.map +1 -1
- package/bundles/cdk-layout.umd.min.js +1 -1
- package/bundles/cdk-layout.umd.min.js.map +1 -1
- package/bundles/cdk-observers.umd.js +26 -7
- package/bundles/cdk-observers.umd.js.map +1 -1
- package/bundles/cdk-observers.umd.min.js +1 -1
- package/bundles/cdk-observers.umd.min.js.map +1 -1
- package/bundles/cdk-overlay.umd.js +605 -258
- package/bundles/cdk-overlay.umd.js.map +1 -1
- package/bundles/cdk-overlay.umd.min.js +2 -2
- package/bundles/cdk-overlay.umd.min.js.map +1 -1
- package/bundles/cdk-platform.umd.js +50 -28
- package/bundles/cdk-platform.umd.js.map +1 -1
- package/bundles/cdk-platform.umd.min.js.map +1 -1
- package/bundles/cdk-portal.umd.js +14 -7
- package/bundles/cdk-portal.umd.js.map +1 -1
- package/bundles/cdk-portal.umd.min.js.map +1 -1
- package/bundles/cdk-scrolling.umd.js +139 -44
- package/bundles/cdk-scrolling.umd.js.map +1 -1
- package/bundles/cdk-scrolling.umd.min.js +1 -1
- package/bundles/cdk-scrolling.umd.min.js.map +1 -1
- package/bundles/cdk-stepper.umd.js +103 -19
- package/bundles/cdk-stepper.umd.js.map +1 -1
- package/bundles/cdk-stepper.umd.min.js +1 -1
- package/bundles/cdk-stepper.umd.min.js.map +1 -1
- package/bundles/cdk-table.umd.js +182 -48
- package/bundles/cdk-table.umd.js.map +1 -1
- package/bundles/cdk-table.umd.min.js.map +1 -1
- package/bundles/cdk-text-field.umd.js +76 -38
- package/bundles/cdk-text-field.umd.js.map +1 -1
- package/bundles/cdk-text-field.umd.min.js +1 -1
- package/bundles/cdk-text-field.umd.min.js.map +1 -1
- package/bundles/cdk-tree.umd.js +71 -34
- package/bundles/cdk-tree.umd.js.map +1 -1
- package/bundles/cdk-tree.umd.min.js +1 -1
- package/bundles/cdk-tree.umd.min.js.map +1 -1
- package/bundles/cdk.umd.js +5 -4
- package/bundles/cdk.umd.js.map +1 -1
- package/bundles/cdk.umd.min.js +1 -1
- package/bundles/cdk.umd.min.js.map +1 -1
- package/coercion/typings/element.d.ts +13 -0
- package/coercion/typings/index.metadata.json +1 -1
- package/coercion/typings/public-api.d.ts +1 -0
- package/drag-drop/typings/{drag-handle.d.ts → directives/drag-handle.d.ts} +3 -0
- package/drag-drop/typings/{drag-placeholder.d.ts → directives/drag-placeholder.d.ts} +0 -0
- package/drag-drop/typings/{drag-preview.d.ts → directives/drag-preview.d.ts} +0 -0
- package/drag-drop/typings/directives/drag.d.ts +109 -0
- package/{typings/drag-drop → drag-drop/typings/directives}/drop-list-group.d.ts +3 -0
- package/drag-drop/typings/directives/drop-list.d.ts +135 -0
- package/drag-drop/typings/drag-drop-registry.d.ts +8 -3
- package/drag-drop/typings/drag-events.d.ts +14 -7
- package/{typings/esm5/drag-drop/drag.d.ts → drag-drop/typings/drag-ref.d.ts} +152 -82
- package/drag-drop/typings/drop-list-container.d.ts +21 -3
- package/drag-drop/typings/{drop-list.d.ts → drop-list-ref.d.ts} +132 -81
- package/drag-drop/typings/index.d.ts +1 -0
- package/drag-drop/typings/index.metadata.json +1 -1
- package/drag-drop/typings/public-api.d.ts +13 -6
- package/esm2015/a11y.js +337 -190
- package/esm2015/a11y.js.map +1 -1
- package/esm2015/accordion.js +16 -11
- package/esm2015/accordion.js.map +1 -1
- package/esm2015/bidi.js +13 -8
- package/esm2015/bidi.js.map +1 -1
- package/esm2015/cdk.js +7 -6
- package/esm2015/cdk.js.map +1 -1
- package/esm2015/coercion.js +25 -8
- package/esm2015/coercion.js.map +1 -1
- package/esm2015/collections.js +22 -7
- package/esm2015/collections.js.map +1 -1
- package/esm2015/drag-drop.js +1587 -691
- package/esm2015/drag-drop.js.map +1 -1
- package/esm2015/keycodes.js +31 -4
- package/esm2015/keycodes.js.map +1 -1
- package/esm2015/layout.js +29 -19
- package/esm2015/layout.js.map +1 -1
- package/esm2015/observers.js +15 -10
- package/esm2015/observers.js.map +1 -1
- package/esm2015/overlay.js +393 -232
- package/esm2015/overlay.js.map +1 -1
- package/esm2015/platform.js +53 -31
- package/esm2015/platform.js.map +1 -1
- package/esm2015/portal.js +13 -9
- package/esm2015/portal.js.map +1 -1
- package/esm2015/scrolling.js +102 -45
- package/esm2015/scrolling.js.map +1 -1
- package/esm2015/stepper.js +93 -24
- package/esm2015/stepper.js.map +1 -1
- package/esm2015/table.js +89 -45
- package/esm2015/table.js.map +1 -1
- package/esm2015/text-field.js +54 -37
- package/esm2015/text-field.js.map +1 -1
- package/esm2015/tree.js +55 -36
- package/esm2015/tree.js.map +1 -1
- package/esm5/a11y.es5.js +481 -220
- package/esm5/a11y.es5.js.map +1 -1
- package/esm5/accordion.es5.js +18 -11
- package/esm5/accordion.es5.js.map +1 -1
- package/esm5/bidi.es5.js +13 -8
- package/esm5/bidi.es5.js.map +1 -1
- package/esm5/cdk.es5.js +7 -6
- package/esm5/cdk.es5.js.map +1 -1
- package/esm5/coercion.es5.js +25 -8
- package/esm5/coercion.es5.js.map +1 -1
- package/esm5/collections.es5.js +35 -7
- package/esm5/collections.es5.js.map +1 -1
- package/esm5/drag-drop.es5.js +2233 -972
- package/esm5/drag-drop.es5.js.map +1 -1
- package/esm5/keycodes.es5.js +35 -4
- package/esm5/keycodes.es5.js.map +1 -1
- package/esm5/layout.es5.js +31 -24
- package/esm5/layout.es5.js.map +1 -1
- package/esm5/observers.es5.js +29 -10
- package/esm5/observers.es5.js.map +1 -1
- package/esm5/overlay.es5.js +609 -262
- package/esm5/overlay.es5.js.map +1 -1
- package/esm5/platform.es5.js +52 -30
- package/esm5/platform.es5.js.map +1 -1
- package/esm5/portal.es5.js +16 -9
- package/esm5/portal.es5.js.map +1 -1
- package/esm5/scrolling.es5.js +141 -46
- package/esm5/scrolling.es5.js.map +1 -1
- package/esm5/stepper.es5.js +106 -24
- package/esm5/stepper.es5.js.map +1 -1
- package/esm5/table.es5.js +184 -50
- package/esm5/table.es5.js.map +1 -1
- package/esm5/text-field.es5.js +75 -37
- package/esm5/text-field.es5.js.map +1 -1
- package/esm5/tree.es5.js +74 -37
- package/esm5/tree.es5.js.map +1 -1
- package/keycodes/typings/index.metadata.json +1 -1
- package/keycodes/typings/modifiers.d.ts +14 -0
- package/keycodes/typings/public-api.d.ts +1 -0
- package/overlay/typings/index.metadata.json +1 -1
- package/overlay/typings/overlay-directives.d.ts +0 -2
- package/package.json +4 -4
- package/schematics/ng-generate/drag-drop/files/__path__/__name@dasherize@if-flat__/__name@dasherize__.component.ts +2 -2
- package/schematics/ng-update/upgrade-data.js +2 -1
- package/schematics/ng-update/upgrade-data.js.map +1 -1
- package/schematics/ng-update/upgrade-rules/index.js +3 -2
- package/schematics/ng-update/upgrade-rules/index.js.map +1 -1
- package/schematics/utils/ast/ng-module-imports.d.ts +1 -1
- package/schematics/utils/ast/ng-module-imports.js +25 -13
- package/schematics/utils/ast/ng-module-imports.js.map +1 -1
- package/schematics/utils/get-project.js +2 -1
- package/schematics/utils/get-project.js.map +1 -1
- package/schematics/utils/parse5-element.js +3 -2
- package/schematics/utils/parse5-element.js.map +1 -1
- package/schematics/utils/project-targets.js +2 -1
- package/schematics/utils/project-targets.js.map +1 -1
- package/schematics/utils/version-agnostic-typescript.js +3 -2
- package/schematics/utils/version-agnostic-typescript.js.map +1 -1
- package/scrolling/typings/index.metadata.json +1 -1
- package/stepper/typings/index.metadata.json +1 -1
- package/stepper/typings/public-api.d.ts +1 -0
- package/stepper/typings/step-header.d.ts +15 -0
- package/stepper/typings/stepper.d.ts +11 -1
- package/text-field/typings/autosize.d.ts +6 -0
- package/text-field/typings/index.metadata.json +1 -1
- package/tree/typings/control/base-tree-control.d.ts +1 -1
- package/tree/typings/control/nested-tree-control.d.ts +2 -2
- package/tree/typings/control/tree-control.d.ts +1 -1
- package/tree/typings/nested-node.d.ts +5 -5
- package/typings/a11y/focus-monitor/focus-monitor.d.ts +20 -5
- package/typings/a11y/focus-trap/focus-trap.d.ts +2 -0
- package/typings/a11y/index.metadata.json +1 -1
- package/typings/a11y/live-announcer/live-announcer.d.ts +34 -3
- package/typings/coercion/element.d.ts +13 -0
- package/typings/coercion/index.metadata.json +1 -1
- package/typings/coercion/public-api.d.ts +1 -0
- package/typings/{esm5/drag-drop → drag-drop/directives}/drag-handle.d.ts +3 -0
- package/typings/drag-drop/{drag-placeholder.d.ts → directives/drag-placeholder.d.ts} +0 -0
- package/typings/drag-drop/{drag-preview.d.ts → directives/drag-preview.d.ts} +0 -0
- package/typings/drag-drop/directives/drag.d.ts +109 -0
- package/typings/{esm5/drag-drop → drag-drop/directives}/drop-list-group.d.ts +3 -0
- package/typings/drag-drop/directives/drop-list.d.ts +135 -0
- package/typings/drag-drop/drag-drop-registry.d.ts +8 -3
- package/typings/drag-drop/drag-events.d.ts +14 -7
- package/typings/drag-drop/{drag.d.ts → drag-ref.d.ts} +152 -82
- package/typings/drag-drop/drop-list-container.d.ts +21 -3
- package/typings/{esm5/drag-drop/drop-list.d.ts → drag-drop/drop-list-ref.d.ts} +132 -81
- package/typings/drag-drop/index.d.ts +1 -0
- package/typings/drag-drop/index.metadata.json +1 -1
- package/typings/drag-drop/public-api.d.ts +13 -6
- package/typings/esm5/a11y/focus-monitor/focus-monitor.d.ts +20 -5
- package/typings/esm5/a11y/focus-trap/focus-trap.d.ts +2 -0
- package/typings/esm5/a11y/index.metadata.json +1 -1
- package/typings/esm5/a11y/live-announcer/live-announcer.d.ts +34 -3
- package/typings/esm5/coercion/element.d.ts +13 -0
- package/typings/esm5/coercion/index.metadata.json +1 -1
- package/typings/esm5/coercion/public-api.d.ts +1 -0
- package/typings/{drag-drop → esm5/drag-drop/directives}/drag-handle.d.ts +3 -0
- package/typings/esm5/drag-drop/{drag-placeholder.d.ts → directives/drag-placeholder.d.ts} +0 -0
- package/typings/esm5/drag-drop/{drag-preview.d.ts → directives/drag-preview.d.ts} +0 -0
- package/typings/esm5/drag-drop/directives/drag.d.ts +109 -0
- package/{drag-drop/typings → typings/esm5/drag-drop/directives}/drop-list-group.d.ts +3 -0
- package/typings/esm5/drag-drop/directives/drop-list.d.ts +135 -0
- package/typings/esm5/drag-drop/drag-drop-registry.d.ts +8 -3
- package/typings/esm5/drag-drop/drag-events.d.ts +14 -7
- package/{drag-drop/typings/drag.d.ts → typings/esm5/drag-drop/drag-ref.d.ts} +152 -82
- package/typings/esm5/drag-drop/drop-list-container.d.ts +21 -3
- package/typings/{drag-drop/drop-list.d.ts → esm5/drag-drop/drop-list-ref.d.ts} +132 -81
- package/typings/esm5/drag-drop/index.d.ts +1 -0
- package/typings/esm5/drag-drop/index.metadata.json +1 -1
- package/typings/esm5/drag-drop/public-api.d.ts +13 -6
- package/typings/esm5/index.metadata.json +1 -1
- package/typings/esm5/keycodes/index.metadata.json +1 -1
- package/typings/esm5/keycodes/modifiers.d.ts +14 -0
- package/typings/esm5/keycodes/public-api.d.ts +1 -0
- package/typings/esm5/overlay/index.metadata.json +1 -1
- package/typings/esm5/overlay/overlay-directives.d.ts +0 -2
- package/typings/esm5/scrolling/index.metadata.json +1 -1
- package/typings/esm5/stepper/index.metadata.json +1 -1
- package/typings/esm5/stepper/public-api.d.ts +1 -0
- package/typings/esm5/stepper/step-header.d.ts +15 -0
- package/typings/esm5/stepper/stepper.d.ts +11 -1
- package/typings/esm5/text-field/autosize.d.ts +6 -0
- package/typings/esm5/text-field/index.metadata.json +1 -1
- package/typings/esm5/tree/control/base-tree-control.d.ts +1 -1
- package/typings/esm5/tree/control/nested-tree-control.d.ts +2 -2
- package/typings/esm5/tree/control/tree-control.d.ts +1 -1
- package/typings/esm5/tree/nested-node.d.ts +5 -5
- package/typings/index.metadata.json +1 -1
- package/typings/keycodes/index.metadata.json +1 -1
- package/typings/keycodes/modifiers.d.ts +14 -0
- package/typings/keycodes/public-api.d.ts +1 -0
- package/typings/overlay/index.metadata.json +1 -1
- package/typings/overlay/overlay-directives.d.ts +0 -2
- package/typings/schematics/utils/ast/ng-module-imports.d.ts +1 -1
- package/typings/scrolling/index.metadata.json +1 -1
- package/typings/stepper/index.metadata.json +1 -1
- package/typings/stepper/public-api.d.ts +1 -0
- package/typings/stepper/step-header.d.ts +15 -0
- package/typings/stepper/stepper.d.ts +11 -1
- package/typings/text-field/autosize.d.ts +6 -0
- package/typings/text-field/index.metadata.json +1 -1
- package/typings/tree/control/base-tree-control.d.ts +1 -1
- package/typings/tree/control/nested-tree-control.d.ts +2 -2
- package/typings/tree/control/tree-control.d.ts +1 -1
- package/typings/tree/nested-node.d.ts +5 -5
package/esm2015/a11y.js
CHANGED
|
@@ -8,20 +8,21 @@
|
|
|
8
8
|
import { DOCUMENT, CommonModule } from '@angular/common';
|
|
9
9
|
import { Inject, Injectable, Optional, SkipSelf, QueryList, Directive, ElementRef, Input, NgZone, isDevMode, InjectionToken, EventEmitter, Output, NgModule, defineInjectable, inject } from '@angular/core';
|
|
10
10
|
import { Subject, Subscription, of } from 'rxjs';
|
|
11
|
-
import { UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, TAB, A, Z, ZERO, NINE } from '@angular/cdk/keycodes';
|
|
11
|
+
import { UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, TAB, A, Z, ZERO, NINE, hasModifierKey } from '@angular/cdk/keycodes';
|
|
12
12
|
import { debounceTime, filter, map, tap, take } from 'rxjs/operators';
|
|
13
13
|
import { Platform, normalizePassiveListenerOptions, PlatformModule } from '@angular/cdk/platform';
|
|
14
|
-
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
14
|
+
import { coerceBooleanProperty, coerceElement } from '@angular/cdk/coercion';
|
|
15
15
|
import { ContentObserver, ObserversModule } from '@angular/cdk/observers';
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @fileoverview added by tsickle
|
|
19
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
19
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
23
|
* IDs are deliminated by an empty space, as per the spec.
|
|
24
|
-
|
|
24
|
+
* @type {?}
|
|
25
|
+
*/
|
|
25
26
|
const ID_DELIMINATOR = ' ';
|
|
26
27
|
/**
|
|
27
28
|
* Adds the given ID to the specified ARIA attribute on an element.
|
|
@@ -69,31 +70,37 @@ function getAriaReferenceIds(el, attr) {
|
|
|
69
70
|
|
|
70
71
|
/**
|
|
71
72
|
* @fileoverview added by tsickle
|
|
72
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
73
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
73
74
|
*/
|
|
74
|
-
/**
|
|
75
|
+
/**
|
|
75
76
|
* ID used for the body container where all messages are appended.
|
|
76
|
-
|
|
77
|
+
* @type {?}
|
|
78
|
+
*/
|
|
77
79
|
const MESSAGES_CONTAINER_ID = 'cdk-describedby-message-container';
|
|
78
|
-
/**
|
|
80
|
+
/**
|
|
79
81
|
* ID prefix used for each created message element.
|
|
80
|
-
|
|
82
|
+
* @type {?}
|
|
83
|
+
*/
|
|
81
84
|
const CDK_DESCRIBEDBY_ID_PREFIX = 'cdk-describedby-message';
|
|
82
|
-
/**
|
|
85
|
+
/**
|
|
83
86
|
* Attribute given to each host element that is described by a message element.
|
|
84
|
-
|
|
87
|
+
* @type {?}
|
|
88
|
+
*/
|
|
85
89
|
const CDK_DESCRIBEDBY_HOST_ATTRIBUTE = 'cdk-describedby-host';
|
|
86
|
-
/**
|
|
90
|
+
/**
|
|
87
91
|
* Global incremental identifier for each registered message element.
|
|
88
|
-
|
|
92
|
+
* @type {?}
|
|
93
|
+
*/
|
|
89
94
|
let nextId = 0;
|
|
90
|
-
/**
|
|
95
|
+
/**
|
|
91
96
|
* Global map of all registered message elements that have been placed into the document.
|
|
92
|
-
|
|
97
|
+
* @type {?}
|
|
98
|
+
*/
|
|
93
99
|
const messageRegistry = new Map();
|
|
94
|
-
/**
|
|
100
|
+
/**
|
|
95
101
|
* Container for all registered messages.
|
|
96
|
-
|
|
102
|
+
* @type {?}
|
|
103
|
+
*/
|
|
97
104
|
let messagesContainer = null;
|
|
98
105
|
/**
|
|
99
106
|
* Utility that creates visually hidden elements with a message content. Useful for elements that
|
|
@@ -168,6 +175,7 @@ class AriaDescriber {
|
|
|
168
175
|
/**
|
|
169
176
|
* Creates a new element in the visually hidden message container element with the message
|
|
170
177
|
* as its content and adds it to the message registry.
|
|
178
|
+
* @private
|
|
171
179
|
* @param {?} message
|
|
172
180
|
* @return {?}
|
|
173
181
|
*/
|
|
@@ -175,13 +183,14 @@ class AriaDescriber {
|
|
|
175
183
|
/** @type {?} */
|
|
176
184
|
const messageElement = this._document.createElement('div');
|
|
177
185
|
messageElement.setAttribute('id', `${CDK_DESCRIBEDBY_ID_PREFIX}-${nextId++}`);
|
|
178
|
-
messageElement.appendChild(/** @type {?} */ (
|
|
179
|
-
this._createMessagesContainer();
|
|
180
|
-
((messagesContainer)).appendChild(messageElement);
|
|
186
|
+
messageElement.appendChild((/** @type {?} */ (this._document.createTextNode(message))));
|
|
187
|
+
this._createMessagesContainer();
|
|
188
|
+
(/** @type {?} */ (messagesContainer)).appendChild(messageElement);
|
|
181
189
|
messageRegistry.set(message, { messageElement, referenceCount: 0 });
|
|
182
190
|
}
|
|
183
191
|
/**
|
|
184
192
|
* Deletes the message element from the global messages container.
|
|
193
|
+
* @private
|
|
185
194
|
* @param {?} message
|
|
186
195
|
* @return {?}
|
|
187
196
|
*/
|
|
@@ -197,6 +206,7 @@ class AriaDescriber {
|
|
|
197
206
|
}
|
|
198
207
|
/**
|
|
199
208
|
* Creates the global container for all aria-describedby messages.
|
|
209
|
+
* @private
|
|
200
210
|
* @return {?}
|
|
201
211
|
*/
|
|
202
212
|
_createMessagesContainer() {
|
|
@@ -208,7 +218,7 @@ class AriaDescriber {
|
|
|
208
218
|
// old container so we don't get duplicates. Doing this, instead of emptying the previous
|
|
209
219
|
// container, should be slightly faster.
|
|
210
220
|
if (preExistingContainer) {
|
|
211
|
-
/** @type {?} */ (
|
|
221
|
+
(/** @type {?} */ (preExistingContainer.parentNode)).removeChild(preExistingContainer);
|
|
212
222
|
}
|
|
213
223
|
messagesContainer = this._document.createElement('div');
|
|
214
224
|
messagesContainer.id = MESSAGES_CONTAINER_ID;
|
|
@@ -219,6 +229,7 @@ class AriaDescriber {
|
|
|
219
229
|
}
|
|
220
230
|
/**
|
|
221
231
|
* Deletes the global messages container.
|
|
232
|
+
* @private
|
|
222
233
|
* @return {?}
|
|
223
234
|
*/
|
|
224
235
|
_deleteMessagesContainer() {
|
|
@@ -229,10 +240,12 @@ class AriaDescriber {
|
|
|
229
240
|
}
|
|
230
241
|
/**
|
|
231
242
|
* Removes all cdk-describedby messages that are hosted through the element.
|
|
243
|
+
* @private
|
|
232
244
|
* @param {?} element
|
|
233
245
|
* @return {?}
|
|
234
246
|
*/
|
|
235
247
|
_removeCdkDescribedByReferenceIds(element) {
|
|
248
|
+
// Remove all aria-describedby reference IDs that are prefixed by CDK_DESCRIBEDBY_ID_PREFIX
|
|
236
249
|
/** @type {?} */
|
|
237
250
|
const originalReferenceIds = getAriaReferenceIds(element, 'aria-describedby')
|
|
238
251
|
.filter(id => id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0);
|
|
@@ -241,13 +254,14 @@ class AriaDescriber {
|
|
|
241
254
|
/**
|
|
242
255
|
* Adds a message reference to the element using aria-describedby and increments the registered
|
|
243
256
|
* message's reference count.
|
|
257
|
+
* @private
|
|
244
258
|
* @param {?} element
|
|
245
259
|
* @param {?} message
|
|
246
260
|
* @return {?}
|
|
247
261
|
*/
|
|
248
262
|
_addMessageReference(element, message) {
|
|
249
263
|
/** @type {?} */
|
|
250
|
-
const registeredMessage = /** @type {?} */ (
|
|
264
|
+
const registeredMessage = (/** @type {?} */ (messageRegistry.get(message)));
|
|
251
265
|
// Add the aria-describedby reference and set the
|
|
252
266
|
// describedby_host attribute to mark the element.
|
|
253
267
|
addAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
|
|
@@ -257,19 +271,21 @@ class AriaDescriber {
|
|
|
257
271
|
/**
|
|
258
272
|
* Removes a message reference from the element using aria-describedby
|
|
259
273
|
* and decrements the registered message's reference count.
|
|
274
|
+
* @private
|
|
260
275
|
* @param {?} element
|
|
261
276
|
* @param {?} message
|
|
262
277
|
* @return {?}
|
|
263
278
|
*/
|
|
264
279
|
_removeMessageReference(element, message) {
|
|
265
280
|
/** @type {?} */
|
|
266
|
-
const registeredMessage = /** @type {?} */ (
|
|
281
|
+
const registeredMessage = (/** @type {?} */ (messageRegistry.get(message)));
|
|
267
282
|
registeredMessage.referenceCount--;
|
|
268
283
|
removeAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
|
|
269
284
|
element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
|
|
270
285
|
}
|
|
271
286
|
/**
|
|
272
287
|
* Returns true if the element has been described by the provided message ID.
|
|
288
|
+
* @private
|
|
273
289
|
* @param {?} element
|
|
274
290
|
* @param {?} message
|
|
275
291
|
* @return {?}
|
|
@@ -285,6 +301,7 @@ class AriaDescriber {
|
|
|
285
301
|
}
|
|
286
302
|
/**
|
|
287
303
|
* Determines whether a message can be described on a particular element.
|
|
304
|
+
* @private
|
|
288
305
|
* @param {?} element
|
|
289
306
|
* @param {?} message
|
|
290
307
|
* @return {?}
|
|
@@ -311,24 +328,24 @@ AriaDescriber.ctorParameters = () => [
|
|
|
311
328
|
function ARIA_DESCRIBER_PROVIDER_FACTORY(parentDispatcher, _document) {
|
|
312
329
|
return parentDispatcher || new AriaDescriber(_document);
|
|
313
330
|
}
|
|
314
|
-
/**
|
|
331
|
+
/**
|
|
315
332
|
* \@docs-private \@deprecated \@breaking-change 8.0.0
|
|
316
|
-
|
|
333
|
+
* @type {?}
|
|
334
|
+
*/
|
|
317
335
|
const ARIA_DESCRIBER_PROVIDER = {
|
|
318
336
|
// If there is already an AriaDescriber available, use that. Otherwise, provide a new one.
|
|
319
337
|
provide: AriaDescriber,
|
|
320
338
|
deps: [
|
|
321
339
|
[new Optional(), new SkipSelf(), AriaDescriber],
|
|
322
|
-
/** @type {?} */ (DOCUMENT)
|
|
340
|
+
(/** @type {?} */ (DOCUMENT))
|
|
323
341
|
],
|
|
324
342
|
useFactory: ARIA_DESCRIBER_PROVIDER_FACTORY
|
|
325
343
|
};
|
|
326
344
|
|
|
327
345
|
/**
|
|
328
346
|
* @fileoverview added by tsickle
|
|
329
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
347
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
330
348
|
*/
|
|
331
|
-
// unsupported: template constraints.
|
|
332
349
|
/**
|
|
333
350
|
* This class manages keyboard events for selectable lists. If you pass it a query list
|
|
334
351
|
* of items, it will set the active item correctly when arrow events occur.
|
|
@@ -341,6 +358,7 @@ class ListKeyManager {
|
|
|
341
358
|
constructor(_items) {
|
|
342
359
|
this._items = _items;
|
|
343
360
|
this._activeItemIndex = -1;
|
|
361
|
+
this._activeItem = null;
|
|
344
362
|
this._wrap = false;
|
|
345
363
|
this._letterKeyStream = new Subject();
|
|
346
364
|
this._typeaheadSubscription = Subscription.EMPTY;
|
|
@@ -351,6 +369,7 @@ class ListKeyManager {
|
|
|
351
369
|
* by the key manager. By default, disabled items are skipped.
|
|
352
370
|
*/
|
|
353
371
|
this._skipPredicateFn = (item) => item.disabled;
|
|
372
|
+
// Buffer for the letters that the user has pressed when the typeahead option is turned on.
|
|
354
373
|
this._pressedLetters = [];
|
|
355
374
|
/**
|
|
356
375
|
* Stream that emits any time the TAB key is pressed, so components can react
|
|
@@ -381,83 +400,96 @@ class ListKeyManager {
|
|
|
381
400
|
/**
|
|
382
401
|
* Sets the predicate function that determines which items should be skipped by the
|
|
383
402
|
* list key manager.
|
|
403
|
+
* @template THIS
|
|
404
|
+
* @this {THIS}
|
|
384
405
|
* @param {?} predicate Function that determines whether the given item should be skipped.
|
|
385
|
-
* @return {
|
|
406
|
+
* @return {THIS}
|
|
386
407
|
*/
|
|
387
408
|
skipPredicate(predicate) {
|
|
388
|
-
this._skipPredicateFn = predicate;
|
|
389
|
-
return this;
|
|
409
|
+
(/** @type {?} */ (this))._skipPredicateFn = predicate;
|
|
410
|
+
return (/** @type {?} */ (this));
|
|
390
411
|
}
|
|
391
412
|
/**
|
|
392
413
|
* Configures wrapping mode, which determines whether the active item will wrap to
|
|
393
414
|
* the other end of list when there are no more items in the given direction.
|
|
415
|
+
* @template THIS
|
|
416
|
+
* @this {THIS}
|
|
394
417
|
* @param {?=} shouldWrap Whether the list should wrap when reaching the end.
|
|
395
|
-
* @return {
|
|
418
|
+
* @return {THIS}
|
|
396
419
|
*/
|
|
397
420
|
withWrap(shouldWrap = true) {
|
|
398
|
-
this._wrap = shouldWrap;
|
|
399
|
-
return this;
|
|
421
|
+
(/** @type {?} */ (this))._wrap = shouldWrap;
|
|
422
|
+
return (/** @type {?} */ (this));
|
|
400
423
|
}
|
|
401
424
|
/**
|
|
402
425
|
* Configures whether the key manager should be able to move the selection vertically.
|
|
426
|
+
* @template THIS
|
|
427
|
+
* @this {THIS}
|
|
403
428
|
* @param {?=} enabled Whether vertical selection should be enabled.
|
|
404
|
-
* @return {
|
|
429
|
+
* @return {THIS}
|
|
405
430
|
*/
|
|
406
431
|
withVerticalOrientation(enabled = true) {
|
|
407
|
-
this._vertical = enabled;
|
|
408
|
-
return this;
|
|
432
|
+
(/** @type {?} */ (this))._vertical = enabled;
|
|
433
|
+
return (/** @type {?} */ (this));
|
|
409
434
|
}
|
|
410
435
|
/**
|
|
411
436
|
* Configures the key manager to move the selection horizontally.
|
|
412
437
|
* Passing in `null` will disable horizontal movement.
|
|
438
|
+
* @template THIS
|
|
439
|
+
* @this {THIS}
|
|
413
440
|
* @param {?} direction Direction in which the selection can be moved.
|
|
414
|
-
* @return {
|
|
441
|
+
* @return {THIS}
|
|
415
442
|
*/
|
|
416
443
|
withHorizontalOrientation(direction) {
|
|
417
|
-
this._horizontal = direction;
|
|
418
|
-
return this;
|
|
444
|
+
(/** @type {?} */ (this))._horizontal = direction;
|
|
445
|
+
return (/** @type {?} */ (this));
|
|
419
446
|
}
|
|
420
447
|
/**
|
|
421
448
|
* Modifier keys which are allowed to be held down and whose default actions will be prevented
|
|
422
449
|
* as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.
|
|
450
|
+
* @template THIS
|
|
451
|
+
* @this {THIS}
|
|
423
452
|
* @param {?} keys
|
|
424
|
-
* @return {
|
|
453
|
+
* @return {THIS}
|
|
425
454
|
*/
|
|
426
455
|
withAllowedModifierKeys(keys) {
|
|
427
|
-
this._allowedModifierKeys = keys;
|
|
428
|
-
return this;
|
|
456
|
+
(/** @type {?} */ (this))._allowedModifierKeys = keys;
|
|
457
|
+
return (/** @type {?} */ (this));
|
|
429
458
|
}
|
|
430
459
|
/**
|
|
431
460
|
* Turns on typeahead mode which allows users to set the active item by typing.
|
|
461
|
+
* @template THIS
|
|
462
|
+
* @this {THIS}
|
|
432
463
|
* @param {?=} debounceInterval Time to wait after the last keystroke before setting the active item.
|
|
433
|
-
* @return {
|
|
464
|
+
* @return {THIS}
|
|
434
465
|
*/
|
|
435
466
|
withTypeAhead(debounceInterval = 200) {
|
|
436
|
-
if (this._items.length && this._items.some(item => typeof item.getLabel !== 'function')) {
|
|
467
|
+
if ((/** @type {?} */ (this))._items.length && (/** @type {?} */ (this))._items.some(item => typeof item.getLabel !== 'function')) {
|
|
437
468
|
throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');
|
|
438
469
|
}
|
|
439
|
-
this._typeaheadSubscription.unsubscribe();
|
|
470
|
+
(/** @type {?} */ (this))._typeaheadSubscription.unsubscribe();
|
|
440
471
|
// Debounce the presses of non-navigational keys, collect the ones that correspond to letters
|
|
441
472
|
// and convert those letters back into a string. Afterwards find the first item that starts
|
|
442
473
|
// with that string and select it.
|
|
443
|
-
this._typeaheadSubscription = this._letterKeyStream.pipe(tap(keyCode => this._pressedLetters.push(keyCode)), debounceTime(debounceInterval), filter(() => this._pressedLetters.length > 0), map(() => this._pressedLetters.join(''))).subscribe(inputString => {
|
|
474
|
+
(/** @type {?} */ (this))._typeaheadSubscription = (/** @type {?} */ (this))._letterKeyStream.pipe(tap(keyCode => (/** @type {?} */ (this))._pressedLetters.push(keyCode)), debounceTime(debounceInterval), filter(() => (/** @type {?} */ (this))._pressedLetters.length > 0), map(() => (/** @type {?} */ (this))._pressedLetters.join(''))).subscribe(inputString => {
|
|
444
475
|
/** @type {?} */
|
|
445
|
-
const items = this._getItemsArray();
|
|
476
|
+
const items = (/** @type {?} */ (this))._getItemsArray();
|
|
446
477
|
// Start at 1 because we want to start searching at the item immediately
|
|
447
478
|
// following the current active item.
|
|
448
479
|
for (let i = 1; i < items.length + 1; i++) {
|
|
449
480
|
/** @type {?} */
|
|
450
|
-
const index = (this._activeItemIndex + i) % items.length;
|
|
481
|
+
const index = ((/** @type {?} */ (this))._activeItemIndex + i) % items.length;
|
|
451
482
|
/** @type {?} */
|
|
452
483
|
const item = items[index];
|
|
453
|
-
if (!
|
|
454
|
-
|
|
484
|
+
if (!(/** @type {?} */ (this))._skipPredicateFn(item) &&
|
|
485
|
+
(/** @type {?} */ (item.getLabel))().toUpperCase().trim().indexOf(inputString) === 0) {
|
|
486
|
+
(/** @type {?} */ (this)).setActiveItem(index);
|
|
455
487
|
break;
|
|
456
488
|
}
|
|
457
489
|
}
|
|
458
|
-
this._pressedLetters = [];
|
|
490
|
+
(/** @type {?} */ (this))._pressedLetters = [];
|
|
459
491
|
});
|
|
460
|
-
return this;
|
|
492
|
+
return (/** @type {?} */ (this));
|
|
461
493
|
}
|
|
462
494
|
/**
|
|
463
495
|
* @param {?} item
|
|
@@ -522,13 +554,15 @@ class ListKeyManager {
|
|
|
522
554
|
return;
|
|
523
555
|
}
|
|
524
556
|
default:
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
557
|
+
if (isModifierAllowed || hasModifierKey(event, 'shiftKey')) {
|
|
558
|
+
// Attempt to use the `event.key` which also maps it to the user's keyboard language,
|
|
559
|
+
// otherwise fall back to resolving alphanumeric characters via the keyCode.
|
|
560
|
+
if (event.key && event.key.length === 1) {
|
|
561
|
+
this._letterKeyStream.next(event.key.toLocaleUpperCase());
|
|
562
|
+
}
|
|
563
|
+
else if ((keyCode >= A && keyCode <= Z) || (keyCode >= ZERO && keyCode <= NINE)) {
|
|
564
|
+
this._letterKeyStream.next(String.fromCharCode(keyCode));
|
|
565
|
+
}
|
|
532
566
|
}
|
|
533
567
|
// Note that we return here, in order to avoid preventing
|
|
534
568
|
// the default action of non-navigational keys.
|
|
@@ -589,8 +623,11 @@ class ListKeyManager {
|
|
|
589
623
|
const itemArray = this._getItemsArray();
|
|
590
624
|
/** @type {?} */
|
|
591
625
|
const index = typeof item === 'number' ? item : itemArray.indexOf(item);
|
|
626
|
+
/** @type {?} */
|
|
627
|
+
const activeItem = itemArray[index];
|
|
628
|
+
// Explicitly check for `null` and `undefined` because other falsy values are valid.
|
|
629
|
+
this._activeItem = activeItem == null ? null : activeItem;
|
|
592
630
|
this._activeItemIndex = index;
|
|
593
|
-
this._activeItem = itemArray[index];
|
|
594
631
|
}
|
|
595
632
|
/**
|
|
596
633
|
* Allows setting of the activeItemIndex without any other effects.
|
|
@@ -606,6 +643,7 @@ class ListKeyManager {
|
|
|
606
643
|
* This method sets the active item, given a list of items and the delta between the
|
|
607
644
|
* currently active item and the new active item. It will calculate differently
|
|
608
645
|
* depending on whether wrap mode is turned on.
|
|
646
|
+
* @private
|
|
609
647
|
* @param {?} delta
|
|
610
648
|
* @return {?}
|
|
611
649
|
*/
|
|
@@ -616,6 +654,7 @@ class ListKeyManager {
|
|
|
616
654
|
* Sets the active item properly given "wrap" mode. In other words, it will continue to move
|
|
617
655
|
* down the list until it finds an item that is not disabled, and it will wrap if it
|
|
618
656
|
* encounters either end of the list.
|
|
657
|
+
* @private
|
|
619
658
|
* @param {?} delta
|
|
620
659
|
* @return {?}
|
|
621
660
|
*/
|
|
@@ -637,6 +676,7 @@ class ListKeyManager {
|
|
|
637
676
|
* Sets the active item properly given the default mode. In other words, it will
|
|
638
677
|
* continue to move down the list until it finds an item that is not disabled. If
|
|
639
678
|
* it encounters either end of the list, it will stop and not wrap.
|
|
679
|
+
* @private
|
|
640
680
|
* @param {?} delta
|
|
641
681
|
* @return {?}
|
|
642
682
|
*/
|
|
@@ -647,6 +687,7 @@ class ListKeyManager {
|
|
|
647
687
|
* Sets the active item to the first enabled item starting at the index specified. If the
|
|
648
688
|
* item is disabled, it will move in the fallbackDelta direction until it either
|
|
649
689
|
* finds an enabled item or encounters the end of the list.
|
|
690
|
+
* @private
|
|
650
691
|
* @param {?} index
|
|
651
692
|
* @param {?} fallbackDelta
|
|
652
693
|
* @return {?}
|
|
@@ -667,6 +708,7 @@ class ListKeyManager {
|
|
|
667
708
|
}
|
|
668
709
|
/**
|
|
669
710
|
* Returns the items as an array.
|
|
711
|
+
* @private
|
|
670
712
|
* @return {?}
|
|
671
713
|
*/
|
|
672
714
|
_getItemsArray() {
|
|
@@ -676,7 +718,7 @@ class ListKeyManager {
|
|
|
676
718
|
|
|
677
719
|
/**
|
|
678
720
|
* @fileoverview added by tsickle
|
|
679
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
721
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
680
722
|
*/
|
|
681
723
|
/**
|
|
682
724
|
* @template T
|
|
@@ -699,7 +741,7 @@ class ActiveDescendantKeyManager extends ListKeyManager {
|
|
|
699
741
|
|
|
700
742
|
/**
|
|
701
743
|
* @fileoverview added by tsickle
|
|
702
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
744
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
703
745
|
*/
|
|
704
746
|
/**
|
|
705
747
|
* @template T
|
|
@@ -711,12 +753,14 @@ class FocusKeyManager extends ListKeyManager {
|
|
|
711
753
|
}
|
|
712
754
|
/**
|
|
713
755
|
* Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.
|
|
756
|
+
* @template THIS
|
|
757
|
+
* @this {THIS}
|
|
714
758
|
* @param {?} origin Focus origin to be used when focusing items.
|
|
715
|
-
* @return {
|
|
759
|
+
* @return {THIS}
|
|
716
760
|
*/
|
|
717
761
|
setFocusOrigin(origin) {
|
|
718
|
-
this._origin = origin;
|
|
719
|
-
return this;
|
|
762
|
+
(/** @type {?} */ (this))._origin = origin;
|
|
763
|
+
return (/** @type {?} */ (this));
|
|
720
764
|
}
|
|
721
765
|
/**
|
|
722
766
|
* @param {?} item
|
|
@@ -732,8 +776,11 @@ class FocusKeyManager extends ListKeyManager {
|
|
|
732
776
|
|
|
733
777
|
/**
|
|
734
778
|
* @fileoverview added by tsickle
|
|
735
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
779
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
736
780
|
*/
|
|
781
|
+
// The InteractivityChecker leans heavily on the ally.js accessibility utilities.
|
|
782
|
+
// Methods like `isTabbable` are only covering specific edge-cases for the browsers which are
|
|
783
|
+
// supported.
|
|
737
784
|
/**
|
|
738
785
|
* Utility for checking the interactivity of an element, such as whether is is focusable or
|
|
739
786
|
* tabbable.
|
|
@@ -869,7 +916,7 @@ InteractivityChecker.ctorParameters = () => [
|
|
|
869
916
|
*/
|
|
870
917
|
function getFrameElement(window) {
|
|
871
918
|
try {
|
|
872
|
-
return /** @type {?} */ (window.frameElement);
|
|
919
|
+
return (/** @type {?} */ (window.frameElement));
|
|
873
920
|
}
|
|
874
921
|
catch (_a) {
|
|
875
922
|
return null;
|
|
@@ -958,6 +1005,7 @@ function getTabIndexValue(element) {
|
|
|
958
1005
|
if (!hasValidTabIndex(element)) {
|
|
959
1006
|
return null;
|
|
960
1007
|
}
|
|
1008
|
+
// See browser issue in Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054
|
|
961
1009
|
/** @type {?} */
|
|
962
1010
|
const tabIndex = parseInt(element.getAttribute('tabindex') || '', 10);
|
|
963
1011
|
return isNaN(tabIndex) ? -1 : tabIndex;
|
|
@@ -971,7 +1019,7 @@ function isPotentiallyTabbableIOS(element) {
|
|
|
971
1019
|
/** @type {?} */
|
|
972
1020
|
let nodeName = element.nodeName.toLowerCase();
|
|
973
1021
|
/** @type {?} */
|
|
974
|
-
let inputType = nodeName === 'input' && (/** @type {?} */ (element)).type;
|
|
1022
|
+
let inputType = nodeName === 'input' && ((/** @type {?} */ (element))).type;
|
|
975
1023
|
return inputType === 'text'
|
|
976
1024
|
|| inputType === 'password'
|
|
977
1025
|
|| nodeName === 'select'
|
|
@@ -1005,7 +1053,7 @@ function getWindow(node) {
|
|
|
1005
1053
|
|
|
1006
1054
|
/**
|
|
1007
1055
|
* @fileoverview added by tsickle
|
|
1008
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
1056
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1009
1057
|
*/
|
|
1010
1058
|
/**
|
|
1011
1059
|
* Class that allows for trapping focus within a DOM element.
|
|
@@ -1028,6 +1076,9 @@ class FocusTrap {
|
|
|
1028
1076
|
this._ngZone = _ngZone;
|
|
1029
1077
|
this._document = _document;
|
|
1030
1078
|
this._hasAttached = false;
|
|
1079
|
+
// Event listeners for the anchors. Need to be regular functions so that we can unbind them later.
|
|
1080
|
+
this._startAnchorListener = () => this.focusLastTabbableElement();
|
|
1081
|
+
this._endAnchorListener = () => this.focusFirstTabbableElement();
|
|
1031
1082
|
this._enabled = true;
|
|
1032
1083
|
if (!deferAnchors) {
|
|
1033
1084
|
this.attachAnchors();
|
|
@@ -1054,11 +1105,21 @@ class FocusTrap {
|
|
|
1054
1105
|
* @return {?}
|
|
1055
1106
|
*/
|
|
1056
1107
|
destroy() {
|
|
1057
|
-
|
|
1058
|
-
|
|
1108
|
+
/** @type {?} */
|
|
1109
|
+
const startAnchor = this._startAnchor;
|
|
1110
|
+
/** @type {?} */
|
|
1111
|
+
const endAnchor = this._endAnchor;
|
|
1112
|
+
if (startAnchor) {
|
|
1113
|
+
startAnchor.removeEventListener('focus', this._startAnchorListener);
|
|
1114
|
+
if (startAnchor.parentNode) {
|
|
1115
|
+
startAnchor.parentNode.removeChild(startAnchor);
|
|
1116
|
+
}
|
|
1059
1117
|
}
|
|
1060
|
-
if (
|
|
1061
|
-
|
|
1118
|
+
if (endAnchor) {
|
|
1119
|
+
endAnchor.removeEventListener('focus', this._endAnchorListener);
|
|
1120
|
+
if (endAnchor.parentNode) {
|
|
1121
|
+
endAnchor.parentNode.removeChild(endAnchor);
|
|
1122
|
+
}
|
|
1062
1123
|
}
|
|
1063
1124
|
this._startAnchor = this._endAnchor = null;
|
|
1064
1125
|
}
|
|
@@ -1075,17 +1136,17 @@ class FocusTrap {
|
|
|
1075
1136
|
}
|
|
1076
1137
|
this._ngZone.runOutsideAngular(() => {
|
|
1077
1138
|
if (!this._startAnchor) {
|
|
1078
|
-
this._startAnchor = this._createAnchor();
|
|
1079
|
-
((this._startAnchor)).addEventListener('focus',
|
|
1139
|
+
this._startAnchor = this._createAnchor();
|
|
1140
|
+
(/** @type {?} */ (this._startAnchor)).addEventListener('focus', this._startAnchorListener);
|
|
1080
1141
|
}
|
|
1081
1142
|
if (!this._endAnchor) {
|
|
1082
|
-
this._endAnchor = this._createAnchor();
|
|
1083
|
-
((this._endAnchor)).addEventListener('focus',
|
|
1143
|
+
this._endAnchor = this._createAnchor();
|
|
1144
|
+
(/** @type {?} */ (this._endAnchor)).addEventListener('focus', this._endAnchorListener);
|
|
1084
1145
|
}
|
|
1085
1146
|
});
|
|
1086
1147
|
if (this._element.parentNode) {
|
|
1087
|
-
this._element.parentNode.insertBefore(/** @type {?} */ (
|
|
1088
|
-
this._element.parentNode.insertBefore(/** @type {?} */ (
|
|
1148
|
+
this._element.parentNode.insertBefore((/** @type {?} */ (this._startAnchor)), this._element);
|
|
1149
|
+
this._element.parentNode.insertBefore((/** @type {?} */ (this._endAnchor)), this._element.nextSibling);
|
|
1089
1150
|
this._hasAttached = true;
|
|
1090
1151
|
}
|
|
1091
1152
|
return this._hasAttached;
|
|
@@ -1125,14 +1186,16 @@ class FocusTrap {
|
|
|
1125
1186
|
}
|
|
1126
1187
|
/**
|
|
1127
1188
|
* Get the specified boundary element of the trapped region.
|
|
1189
|
+
* @private
|
|
1128
1190
|
* @param {?} bound The boundary to get (start or end of trapped region).
|
|
1129
1191
|
* @return {?} The boundary element.
|
|
1130
1192
|
*/
|
|
1131
1193
|
_getRegionBoundary(bound) {
|
|
1194
|
+
// Contains the deprecated version of selector, for temporary backwards comparability.
|
|
1132
1195
|
/** @type {?} */
|
|
1133
|
-
let markers = /** @type {?} */ (this._element.querySelectorAll(`[cdk-focus-region-${bound}], ` +
|
|
1196
|
+
let markers = (/** @type {?} */ (this._element.querySelectorAll(`[cdk-focus-region-${bound}], ` +
|
|
1134
1197
|
`[cdkFocusRegion${bound}], ` +
|
|
1135
|
-
`[cdk-focus-${bound}]`));
|
|
1198
|
+
`[cdk-focus-${bound}]`)));
|
|
1136
1199
|
for (let i = 0; i < markers.length; i++) {
|
|
1137
1200
|
// @breaking-change 8.0.0
|
|
1138
1201
|
if (markers[i].hasAttribute(`cdk-focus-${bound}`)) {
|
|
@@ -1157,9 +1220,10 @@ class FocusTrap {
|
|
|
1157
1220
|
* @return {?} Whether focus was moved successfuly.
|
|
1158
1221
|
*/
|
|
1159
1222
|
focusInitialElement() {
|
|
1223
|
+
// Contains the deprecated version of selector, for temporary backwards comparability.
|
|
1160
1224
|
/** @type {?} */
|
|
1161
|
-
const redirectToElement = /** @type {?} */ (this._element.querySelector(`[cdk-focus-initial], ` +
|
|
1162
|
-
`[cdkFocusInitial]`));
|
|
1225
|
+
const redirectToElement = (/** @type {?} */ (this._element.querySelector(`[cdk-focus-initial], ` +
|
|
1226
|
+
`[cdkFocusInitial]`)));
|
|
1163
1227
|
if (redirectToElement) {
|
|
1164
1228
|
// @breaking-change 8.0.0
|
|
1165
1229
|
if (redirectToElement.hasAttribute(`cdk-focus-initial`)) {
|
|
@@ -1210,6 +1274,7 @@ class FocusTrap {
|
|
|
1210
1274
|
}
|
|
1211
1275
|
/**
|
|
1212
1276
|
* Get the first tabbable element from a DOM subtree (inclusive).
|
|
1277
|
+
* @private
|
|
1213
1278
|
* @param {?} root
|
|
1214
1279
|
* @return {?}
|
|
1215
1280
|
*/
|
|
@@ -1217,12 +1282,14 @@ class FocusTrap {
|
|
|
1217
1282
|
if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
|
|
1218
1283
|
return root;
|
|
1219
1284
|
}
|
|
1285
|
+
// Iterate in DOM order. Note that IE doesn't have `children` for SVG so we fall
|
|
1286
|
+
// back to `childNodes` which includes text nodes, comments etc.
|
|
1220
1287
|
/** @type {?} */
|
|
1221
1288
|
let children = root.children || root.childNodes;
|
|
1222
1289
|
for (let i = 0; i < children.length; i++) {
|
|
1223
1290
|
/** @type {?} */
|
|
1224
1291
|
let tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
|
|
1225
|
-
this._getFirstTabbableElement(/** @type {?} */ (children[i])) :
|
|
1292
|
+
this._getFirstTabbableElement((/** @type {?} */ (children[i]))) :
|
|
1226
1293
|
null;
|
|
1227
1294
|
if (tabbableChild) {
|
|
1228
1295
|
return tabbableChild;
|
|
@@ -1232,6 +1299,7 @@ class FocusTrap {
|
|
|
1232
1299
|
}
|
|
1233
1300
|
/**
|
|
1234
1301
|
* Get the last tabbable element from a DOM subtree (inclusive).
|
|
1302
|
+
* @private
|
|
1235
1303
|
* @param {?} root
|
|
1236
1304
|
* @return {?}
|
|
1237
1305
|
*/
|
|
@@ -1239,12 +1307,13 @@ class FocusTrap {
|
|
|
1239
1307
|
if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
|
|
1240
1308
|
return root;
|
|
1241
1309
|
}
|
|
1310
|
+
// Iterate in reverse DOM order.
|
|
1242
1311
|
/** @type {?} */
|
|
1243
1312
|
let children = root.children || root.childNodes;
|
|
1244
1313
|
for (let i = children.length - 1; i >= 0; i--) {
|
|
1245
1314
|
/** @type {?} */
|
|
1246
1315
|
let tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
|
|
1247
|
-
this._getLastTabbableElement(/** @type {?} */ (children[i])) :
|
|
1316
|
+
this._getLastTabbableElement((/** @type {?} */ (children[i]))) :
|
|
1248
1317
|
null;
|
|
1249
1318
|
if (tabbableChild) {
|
|
1250
1319
|
return tabbableChild;
|
|
@@ -1254,6 +1323,7 @@ class FocusTrap {
|
|
|
1254
1323
|
}
|
|
1255
1324
|
/**
|
|
1256
1325
|
* Creates an anchor element.
|
|
1326
|
+
* @private
|
|
1257
1327
|
* @return {?}
|
|
1258
1328
|
*/
|
|
1259
1329
|
_createAnchor() {
|
|
@@ -1266,6 +1336,7 @@ class FocusTrap {
|
|
|
1266
1336
|
}
|
|
1267
1337
|
/**
|
|
1268
1338
|
* Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.
|
|
1339
|
+
* @private
|
|
1269
1340
|
* @param {?} isEnabled Whether the focus trap is enabled.
|
|
1270
1341
|
* @param {?} anchor Anchor on which to toggle the tabindex.
|
|
1271
1342
|
* @return {?}
|
|
@@ -1277,6 +1348,7 @@ class FocusTrap {
|
|
|
1277
1348
|
}
|
|
1278
1349
|
/**
|
|
1279
1350
|
* Executes a function when the zone is stable.
|
|
1351
|
+
* @private
|
|
1280
1352
|
* @param {?} fn
|
|
1281
1353
|
* @return {?}
|
|
1282
1354
|
*/
|
|
@@ -1382,7 +1454,7 @@ class CdkTrapFocus {
|
|
|
1382
1454
|
ngAfterContentInit() {
|
|
1383
1455
|
this.focusTrap.attachAnchors();
|
|
1384
1456
|
if (this.autoCapture) {
|
|
1385
|
-
this._previouslyFocusedElement = /** @type {?} */ (this._document.activeElement);
|
|
1457
|
+
this._previouslyFocusedElement = (/** @type {?} */ (this._document.activeElement));
|
|
1386
1458
|
this.focusTrap.focusInitialElementWhenReady();
|
|
1387
1459
|
}
|
|
1388
1460
|
}
|
|
@@ -1414,8 +1486,10 @@ CdkTrapFocus.propDecorators = {
|
|
|
1414
1486
|
|
|
1415
1487
|
/**
|
|
1416
1488
|
* @fileoverview added by tsickle
|
|
1417
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
1489
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1418
1490
|
*/
|
|
1491
|
+
// The token for the live announcer element is defined in a separate file from LiveAnnouncer
|
|
1492
|
+
// as a workaround for https://github.com/angular/angular/issues/22559
|
|
1419
1493
|
/** @type {?} */
|
|
1420
1494
|
const LIVE_ANNOUNCER_ELEMENT_TOKEN = new InjectionToken('liveAnnouncerElement', {
|
|
1421
1495
|
providedIn: 'root',
|
|
@@ -1431,7 +1505,7 @@ function LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY() {
|
|
|
1431
1505
|
|
|
1432
1506
|
/**
|
|
1433
1507
|
* @fileoverview added by tsickle
|
|
1434
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
1508
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1435
1509
|
*/
|
|
1436
1510
|
class LiveAnnouncer {
|
|
1437
1511
|
/**
|
|
@@ -1448,15 +1522,25 @@ class LiveAnnouncer {
|
|
|
1448
1522
|
this._liveElement = elementToken || this._createLiveElement();
|
|
1449
1523
|
}
|
|
1450
1524
|
/**
|
|
1451
|
-
*
|
|
1452
|
-
* @param {
|
|
1453
|
-
* @
|
|
1454
|
-
* @return {?} Promise that will be resolved when the message is added to the DOM.
|
|
1525
|
+
* @param {?} message
|
|
1526
|
+
* @param {...?} args
|
|
1527
|
+
* @return {?}
|
|
1455
1528
|
*/
|
|
1456
|
-
announce(message,
|
|
1457
|
-
|
|
1529
|
+
announce(message, ...args) {
|
|
1530
|
+
/** @type {?} */
|
|
1531
|
+
let politeness;
|
|
1532
|
+
/** @type {?} */
|
|
1533
|
+
let duration;
|
|
1534
|
+
if (args.length === 1 && typeof args[0] === 'number') {
|
|
1535
|
+
duration = args[0];
|
|
1536
|
+
}
|
|
1537
|
+
else {
|
|
1538
|
+
[politeness, duration] = args;
|
|
1539
|
+
}
|
|
1540
|
+
this.clear();
|
|
1541
|
+
clearTimeout(this._previousTimeout);
|
|
1458
1542
|
// TODO: ensure changing the politeness works on all environments we support.
|
|
1459
|
-
this._liveElement.setAttribute('aria-live', politeness);
|
|
1543
|
+
this._liveElement.setAttribute('aria-live', (/** @type {?} */ (politeness)) || 'polite');
|
|
1460
1544
|
// This 100ms timeout is necessary for some browser + screen-reader combinations:
|
|
1461
1545
|
// - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout.
|
|
1462
1546
|
// - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a
|
|
@@ -1468,10 +1552,24 @@ class LiveAnnouncer {
|
|
|
1468
1552
|
this._previousTimeout = setTimeout(() => {
|
|
1469
1553
|
this._liveElement.textContent = message;
|
|
1470
1554
|
resolve();
|
|
1555
|
+
if (typeof duration === 'number') {
|
|
1556
|
+
this._previousTimeout = setTimeout(() => this.clear(), duration);
|
|
1557
|
+
}
|
|
1471
1558
|
}, 100);
|
|
1472
1559
|
});
|
|
1473
1560
|
});
|
|
1474
1561
|
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Clears the current text from the announcer element. Can be used to prevent
|
|
1564
|
+
* screen readers from reading the text out again while the user is going
|
|
1565
|
+
* through the page landmarks.
|
|
1566
|
+
* @return {?}
|
|
1567
|
+
*/
|
|
1568
|
+
clear() {
|
|
1569
|
+
if (this._liveElement) {
|
|
1570
|
+
this._liveElement.textContent = '';
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1475
1573
|
/**
|
|
1476
1574
|
* @return {?}
|
|
1477
1575
|
*/
|
|
@@ -1479,10 +1577,11 @@ class LiveAnnouncer {
|
|
|
1479
1577
|
clearTimeout(this._previousTimeout);
|
|
1480
1578
|
if (this._liveElement && this._liveElement.parentNode) {
|
|
1481
1579
|
this._liveElement.parentNode.removeChild(this._liveElement);
|
|
1482
|
-
this._liveElement = /** @type {?} */ (
|
|
1580
|
+
this._liveElement = (/** @type {?} */ (null));
|
|
1483
1581
|
}
|
|
1484
1582
|
}
|
|
1485
1583
|
/**
|
|
1584
|
+
* @private
|
|
1486
1585
|
* @return {?}
|
|
1487
1586
|
*/
|
|
1488
1587
|
_createLiveElement() {
|
|
@@ -1494,7 +1593,7 @@ class LiveAnnouncer {
|
|
|
1494
1593
|
const liveEl = this._document.createElement('div');
|
|
1495
1594
|
// Remove any old containers. This can happen when coming in from a server-side-rendered page.
|
|
1496
1595
|
for (let i = 0; i < previousElements.length; i++) {
|
|
1497
|
-
/** @type {?} */ (
|
|
1596
|
+
(/** @type {?} */ (previousElements[i].parentNode)).removeChild(previousElements[i]);
|
|
1498
1597
|
}
|
|
1499
1598
|
liveEl.classList.add(elementClass);
|
|
1500
1599
|
liveEl.classList.add('cdk-visually-hidden');
|
|
@@ -1554,6 +1653,7 @@ class CdkAriaLive {
|
|
|
1554
1653
|
return this._contentObserver
|
|
1555
1654
|
.observe(this._elementRef)
|
|
1556
1655
|
.subscribe(() => {
|
|
1656
|
+
// Note that we use textContent here, rather than innerText, in order to avoid a reflow.
|
|
1557
1657
|
/** @type {?} */
|
|
1558
1658
|
const elementText = this._elementRef.nativeElement.textContent;
|
|
1559
1659
|
// The `MutationObserver` fires also for attribute
|
|
@@ -1593,18 +1693,19 @@ CdkAriaLive.propDecorators = {
|
|
|
1593
1693
|
};
|
|
1594
1694
|
/**
|
|
1595
1695
|
* \@docs-private \@deprecated \@breaking-change 8.0.0
|
|
1596
|
-
* @param {?}
|
|
1696
|
+
* @param {?} parentAnnouncer
|
|
1597
1697
|
* @param {?} liveElement
|
|
1598
1698
|
* @param {?} _document
|
|
1599
1699
|
* @param {?} ngZone
|
|
1600
1700
|
* @return {?}
|
|
1601
1701
|
*/
|
|
1602
|
-
function LIVE_ANNOUNCER_PROVIDER_FACTORY(
|
|
1603
|
-
return
|
|
1702
|
+
function LIVE_ANNOUNCER_PROVIDER_FACTORY(parentAnnouncer, liveElement, _document, ngZone) {
|
|
1703
|
+
return parentAnnouncer || new LiveAnnouncer(liveElement, ngZone, _document);
|
|
1604
1704
|
}
|
|
1605
|
-
/**
|
|
1705
|
+
/**
|
|
1606
1706
|
* \@docs-private \@deprecated \@breaking-change 8.0.0
|
|
1607
|
-
|
|
1707
|
+
* @type {?}
|
|
1708
|
+
*/
|
|
1608
1709
|
const LIVE_ANNOUNCER_PROVIDER = {
|
|
1609
1710
|
// If there is already a LiveAnnouncer available, use that. Otherwise, provide a new one.
|
|
1610
1711
|
provide: LiveAnnouncer,
|
|
@@ -1619,10 +1720,21 @@ const LIVE_ANNOUNCER_PROVIDER = {
|
|
|
1619
1720
|
|
|
1620
1721
|
/**
|
|
1621
1722
|
* @fileoverview added by tsickle
|
|
1622
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
1723
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
1623
1724
|
*/
|
|
1725
|
+
// This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found
|
|
1726
|
+
// that a value of around 650ms seems appropriate.
|
|
1624
1727
|
/** @type {?} */
|
|
1625
1728
|
const TOUCH_BUFFER_MS = 650;
|
|
1729
|
+
/**
|
|
1730
|
+
* Event listener options that enable capturing and also
|
|
1731
|
+
* mark the the listener as passive if the browser supports it.
|
|
1732
|
+
* @type {?}
|
|
1733
|
+
*/
|
|
1734
|
+
const captureEventListenerOptions = normalizePassiveListenerOptions({
|
|
1735
|
+
passive: true,
|
|
1736
|
+
capture: true
|
|
1737
|
+
});
|
|
1626
1738
|
/**
|
|
1627
1739
|
* Monitors mouse and keyboard events to determine the cause of focus events.
|
|
1628
1740
|
*/
|
|
@@ -1646,14 +1758,54 @@ class FocusMonitor {
|
|
|
1646
1758
|
* Map of elements being monitored to their info.
|
|
1647
1759
|
*/
|
|
1648
1760
|
this._elementInfo = new Map();
|
|
1649
|
-
/**
|
|
1650
|
-
* A map of global objects to lists of current listeners.
|
|
1651
|
-
*/
|
|
1652
|
-
this._unregisterGlobalListeners = () => { };
|
|
1653
1761
|
/**
|
|
1654
1762
|
* The number of elements currently being monitored.
|
|
1655
1763
|
*/
|
|
1656
1764
|
this._monitoredElementCount = 0;
|
|
1765
|
+
/**
|
|
1766
|
+
* Event listener for `keydown` events on the document.
|
|
1767
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
1768
|
+
*/
|
|
1769
|
+
this._documentKeydownListener = () => {
|
|
1770
|
+
// On keydown record the origin and clear any touch event that may be in progress.
|
|
1771
|
+
this._lastTouchTarget = null;
|
|
1772
|
+
this._setOriginForCurrentEventQueue('keyboard');
|
|
1773
|
+
};
|
|
1774
|
+
/**
|
|
1775
|
+
* Event listener for `mousedown` events on the document.
|
|
1776
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
1777
|
+
*/
|
|
1778
|
+
this._documentMousedownListener = () => {
|
|
1779
|
+
// On mousedown record the origin only if there is not touch
|
|
1780
|
+
// target, since a mousedown can happen as a result of a touch event.
|
|
1781
|
+
if (!this._lastTouchTarget) {
|
|
1782
|
+
this._setOriginForCurrentEventQueue('mouse');
|
|
1783
|
+
}
|
|
1784
|
+
};
|
|
1785
|
+
/**
|
|
1786
|
+
* Event listener for `touchstart` events on the document.
|
|
1787
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
1788
|
+
*/
|
|
1789
|
+
this._documentTouchstartListener = (event) => {
|
|
1790
|
+
// When the touchstart event fires the focus event is not yet in the event queue. This means
|
|
1791
|
+
// we can't rely on the trick used above (setting timeout of 1ms). Instead we wait 650ms to
|
|
1792
|
+
// see if a focus happens.
|
|
1793
|
+
if (this._touchTimeoutId != null) {
|
|
1794
|
+
clearTimeout(this._touchTimeoutId);
|
|
1795
|
+
}
|
|
1796
|
+
this._lastTouchTarget = event.target;
|
|
1797
|
+
this._touchTimeoutId = setTimeout(() => this._lastTouchTarget = null, TOUCH_BUFFER_MS);
|
|
1798
|
+
};
|
|
1799
|
+
/**
|
|
1800
|
+
* Event listener for `focus` events on the window.
|
|
1801
|
+
* Needs to be an arrow function in order to preserve the context when it gets bound.
|
|
1802
|
+
*/
|
|
1803
|
+
this._windowFocusListener = () => {
|
|
1804
|
+
// Make a note of when the window regains focus, so we can
|
|
1805
|
+
// restore the origin info for the focused element.
|
|
1806
|
+
this._windowFocused = true;
|
|
1807
|
+
this._windowFocusTimeoutId = setTimeout(() => this._windowFocused = false);
|
|
1808
|
+
};
|
|
1657
1809
|
}
|
|
1658
1810
|
/**
|
|
1659
1811
|
* @param {?} element
|
|
@@ -1666,14 +1818,15 @@ class FocusMonitor {
|
|
|
1666
1818
|
return of(null);
|
|
1667
1819
|
}
|
|
1668
1820
|
/** @type {?} */
|
|
1669
|
-
const nativeElement =
|
|
1821
|
+
const nativeElement = coerceElement(element);
|
|
1670
1822
|
// Check if we're already monitoring this element.
|
|
1671
1823
|
if (this._elementInfo.has(nativeElement)) {
|
|
1672
1824
|
/** @type {?} */
|
|
1673
|
-
let cachedInfo = this._elementInfo.get(nativeElement);
|
|
1674
|
-
((cachedInfo)).checkChildren = checkChildren;
|
|
1675
|
-
return /** @type {?} */ (
|
|
1825
|
+
let cachedInfo = this._elementInfo.get(nativeElement);
|
|
1826
|
+
(/** @type {?} */ (cachedInfo)).checkChildren = checkChildren;
|
|
1827
|
+
return (/** @type {?} */ (cachedInfo)).subject.asObservable();
|
|
1676
1828
|
}
|
|
1829
|
+
// Create monitored element info.
|
|
1677
1830
|
/** @type {?} */
|
|
1678
1831
|
let info = {
|
|
1679
1832
|
unlisten: () => { },
|
|
@@ -1682,6 +1835,7 @@ class FocusMonitor {
|
|
|
1682
1835
|
};
|
|
1683
1836
|
this._elementInfo.set(nativeElement, info);
|
|
1684
1837
|
this._incrementMonitoredElementCount();
|
|
1838
|
+
// Start listening. We need to listen in capture phase since focus events don't bubble.
|
|
1685
1839
|
/** @type {?} */
|
|
1686
1840
|
let focusListener = (event) => this._onFocus(event, nativeElement);
|
|
1687
1841
|
/** @type {?} */
|
|
@@ -1703,7 +1857,7 @@ class FocusMonitor {
|
|
|
1703
1857
|
*/
|
|
1704
1858
|
stopMonitoring(element) {
|
|
1705
1859
|
/** @type {?} */
|
|
1706
|
-
const nativeElement =
|
|
1860
|
+
const nativeElement = coerceElement(element);
|
|
1707
1861
|
/** @type {?} */
|
|
1708
1862
|
const elementInfo = this._elementInfo.get(nativeElement);
|
|
1709
1863
|
if (elementInfo) {
|
|
@@ -1722,12 +1876,12 @@ class FocusMonitor {
|
|
|
1722
1876
|
*/
|
|
1723
1877
|
focusVia(element, origin, options) {
|
|
1724
1878
|
/** @type {?} */
|
|
1725
|
-
const nativeElement =
|
|
1879
|
+
const nativeElement = coerceElement(element);
|
|
1726
1880
|
this._setOriginForCurrentEventQueue(origin);
|
|
1727
1881
|
// `focus` isn't available on the server
|
|
1728
1882
|
if (typeof nativeElement.focus === 'function') {
|
|
1729
1883
|
// Cast the element to `any`, because the TS typings don't have the `options` parameter yet.
|
|
1730
|
-
(/** @type {?} */ (nativeElement)).focus(options);
|
|
1884
|
+
((/** @type {?} */ (nativeElement))).focus(options);
|
|
1731
1885
|
}
|
|
1732
1886
|
}
|
|
1733
1887
|
/**
|
|
@@ -1737,63 +1891,7 @@ class FocusMonitor {
|
|
|
1737
1891
|
this._elementInfo.forEach((_info, element) => this.stopMonitoring(element));
|
|
1738
1892
|
}
|
|
1739
1893
|
/**
|
|
1740
|
-
*
|
|
1741
|
-
* @return {?}
|
|
1742
|
-
*/
|
|
1743
|
-
_registerGlobalListeners() {
|
|
1744
|
-
// Do nothing if we're not on the browser platform.
|
|
1745
|
-
if (!this._platform.isBrowser) {
|
|
1746
|
-
return;
|
|
1747
|
-
}
|
|
1748
|
-
/** @type {?} */
|
|
1749
|
-
let documentKeydownListener = () => {
|
|
1750
|
-
this._lastTouchTarget = null;
|
|
1751
|
-
this._setOriginForCurrentEventQueue('keyboard');
|
|
1752
|
-
};
|
|
1753
|
-
/** @type {?} */
|
|
1754
|
-
let documentMousedownListener = () => {
|
|
1755
|
-
if (!this._lastTouchTarget) {
|
|
1756
|
-
this._setOriginForCurrentEventQueue('mouse');
|
|
1757
|
-
}
|
|
1758
|
-
};
|
|
1759
|
-
/** @type {?} */
|
|
1760
|
-
let documentTouchstartListener = (event) => {
|
|
1761
|
-
if (this._touchTimeoutId != null) {
|
|
1762
|
-
clearTimeout(this._touchTimeoutId);
|
|
1763
|
-
}
|
|
1764
|
-
this._lastTouchTarget = event.target;
|
|
1765
|
-
this._touchTimeoutId = setTimeout(() => this._lastTouchTarget = null, TOUCH_BUFFER_MS);
|
|
1766
|
-
};
|
|
1767
|
-
/** @type {?} */
|
|
1768
|
-
let windowFocusListener = () => {
|
|
1769
|
-
this._windowFocused = true;
|
|
1770
|
-
this._windowFocusTimeoutId = setTimeout(() => this._windowFocused = false);
|
|
1771
|
-
};
|
|
1772
|
-
/** @type {?} */
|
|
1773
|
-
const captureEventListenerOptions = normalizePassiveListenerOptions({
|
|
1774
|
-
passive: true,
|
|
1775
|
-
capture: true
|
|
1776
|
-
});
|
|
1777
|
-
// Note: we listen to events in the capture phase so we can detect them even if the user stops
|
|
1778
|
-
// propagation.
|
|
1779
|
-
this._ngZone.runOutsideAngular(() => {
|
|
1780
|
-
document.addEventListener('keydown', documentKeydownListener, captureEventListenerOptions);
|
|
1781
|
-
document.addEventListener('mousedown', documentMousedownListener, captureEventListenerOptions);
|
|
1782
|
-
document.addEventListener('touchstart', documentTouchstartListener, captureEventListenerOptions);
|
|
1783
|
-
window.addEventListener('focus', windowFocusListener);
|
|
1784
|
-
});
|
|
1785
|
-
this._unregisterGlobalListeners = () => {
|
|
1786
|
-
document.removeEventListener('keydown', documentKeydownListener, captureEventListenerOptions);
|
|
1787
|
-
document.removeEventListener('mousedown', documentMousedownListener, captureEventListenerOptions);
|
|
1788
|
-
document.removeEventListener('touchstart', documentTouchstartListener, captureEventListenerOptions);
|
|
1789
|
-
window.removeEventListener('focus', windowFocusListener);
|
|
1790
|
-
// Clear timeouts for all potentially pending timeouts to prevent the leaks.
|
|
1791
|
-
clearTimeout(this._windowFocusTimeoutId);
|
|
1792
|
-
clearTimeout(this._touchTimeoutId);
|
|
1793
|
-
clearTimeout(this._originTimeoutId);
|
|
1794
|
-
};
|
|
1795
|
-
}
|
|
1796
|
-
/**
|
|
1894
|
+
* @private
|
|
1797
1895
|
* @param {?} element
|
|
1798
1896
|
* @param {?} className
|
|
1799
1897
|
* @param {?} shouldSet
|
|
@@ -1809,6 +1907,7 @@ class FocusMonitor {
|
|
|
1809
1907
|
}
|
|
1810
1908
|
/**
|
|
1811
1909
|
* Sets the focus classes on the element based on the given focus origin.
|
|
1910
|
+
* @private
|
|
1812
1911
|
* @param {?} element The element to update the classes on.
|
|
1813
1912
|
* @param {?=} origin The focus origin.
|
|
1814
1913
|
* @return {?}
|
|
@@ -1826,6 +1925,7 @@ class FocusMonitor {
|
|
|
1826
1925
|
}
|
|
1827
1926
|
/**
|
|
1828
1927
|
* Sets the origin and schedules an async function to clear it at the end of the event queue.
|
|
1928
|
+
* @private
|
|
1829
1929
|
* @param {?} origin The origin to set.
|
|
1830
1930
|
* @return {?}
|
|
1831
1931
|
*/
|
|
@@ -1840,10 +1940,28 @@ class FocusMonitor {
|
|
|
1840
1940
|
}
|
|
1841
1941
|
/**
|
|
1842
1942
|
* Checks whether the given focus event was caused by a touchstart event.
|
|
1943
|
+
* @private
|
|
1843
1944
|
* @param {?} event The focus event to check.
|
|
1844
1945
|
* @return {?} Whether the event was caused by a touch.
|
|
1845
1946
|
*/
|
|
1846
1947
|
_wasCausedByTouch(event) {
|
|
1948
|
+
// Note(mmalerba): This implementation is not quite perfect, there is a small edge case.
|
|
1949
|
+
// Consider the following dom structure:
|
|
1950
|
+
//
|
|
1951
|
+
// <div #parent tabindex="0" cdkFocusClasses>
|
|
1952
|
+
// <div #child (click)="#parent.focus()"></div>
|
|
1953
|
+
// </div>
|
|
1954
|
+
//
|
|
1955
|
+
// If the user touches the #child element and the #parent is programmatically focused as a
|
|
1956
|
+
// result, this code will still consider it to have been caused by the touch event and will
|
|
1957
|
+
// apply the cdk-touch-focused class rather than the cdk-program-focused class. This is a
|
|
1958
|
+
// relatively small edge-case that can be worked around by using
|
|
1959
|
+
// focusVia(parentEl, 'program') to focus the parent element.
|
|
1960
|
+
//
|
|
1961
|
+
// If we decide that we absolutely must handle this case correctly, we can do so by listening
|
|
1962
|
+
// for the first focus event after the touchstart, and then the first blur event after that
|
|
1963
|
+
// focus event. When that blur event fires we know that whatever follows is not a result of the
|
|
1964
|
+
// touchstart.
|
|
1847
1965
|
/** @type {?} */
|
|
1848
1966
|
let focusTarget = event.target;
|
|
1849
1967
|
return this._lastTouchTarget instanceof Node && focusTarget instanceof Node &&
|
|
@@ -1851,16 +1969,33 @@ class FocusMonitor {
|
|
|
1851
1969
|
}
|
|
1852
1970
|
/**
|
|
1853
1971
|
* Handles focus events on a registered element.
|
|
1972
|
+
* @private
|
|
1854
1973
|
* @param {?} event The focus event.
|
|
1855
1974
|
* @param {?} element The monitored element.
|
|
1856
1975
|
* @return {?}
|
|
1857
1976
|
*/
|
|
1858
1977
|
_onFocus(event, element) {
|
|
1978
|
+
// NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent
|
|
1979
|
+
// focus event affecting the monitored element. If we want to use the origin of the first event
|
|
1980
|
+
// instead we should check for the cdk-focused class here and return if the element already has
|
|
1981
|
+
// it. (This only matters for elements that have includesChildren = true).
|
|
1982
|
+
// NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent
|
|
1983
|
+
// focus event affecting the monitored element. If we want to use the origin of the first event
|
|
1984
|
+
// instead we should check for the cdk-focused class here and return if the element already has
|
|
1985
|
+
// it. (This only matters for elements that have includesChildren = true).
|
|
1986
|
+
// If we are not counting child-element-focus as focused, make sure that the event target is the
|
|
1987
|
+
// monitored element itself.
|
|
1859
1988
|
/** @type {?} */
|
|
1860
1989
|
const elementInfo = this._elementInfo.get(element);
|
|
1861
1990
|
if (!elementInfo || (!elementInfo.checkChildren && element !== event.target)) {
|
|
1862
1991
|
return;
|
|
1863
1992
|
}
|
|
1993
|
+
// If we couldn't detect a cause for the focus event, it's due to one of three reasons:
|
|
1994
|
+
// 1) The window has just regained focus, in which case we want to restore the focused state of
|
|
1995
|
+
// the element from before the window blurred.
|
|
1996
|
+
// 2) It was caused by a touch event, in which case we mark the origin as 'touch'.
|
|
1997
|
+
// 3) The element was programmatically focused, in which case we should mark the origin as
|
|
1998
|
+
// 'program'.
|
|
1864
1999
|
/** @type {?} */
|
|
1865
2000
|
let origin = this._origin;
|
|
1866
2001
|
if (!origin) {
|
|
@@ -1885,6 +2020,8 @@ class FocusMonitor {
|
|
|
1885
2020
|
* @return {?}
|
|
1886
2021
|
*/
|
|
1887
2022
|
_onBlur(event, element) {
|
|
2023
|
+
// If we are counting child-element-focus as focused, make sure that we aren't just blurring in
|
|
2024
|
+
// order to focus another child of the monitored element.
|
|
1888
2025
|
/** @type {?} */
|
|
1889
2026
|
const elementInfo = this._elementInfo.get(element);
|
|
1890
2027
|
if (!elementInfo || (elementInfo.checkChildren && event.relatedTarget instanceof Node &&
|
|
@@ -1895,6 +2032,7 @@ class FocusMonitor {
|
|
|
1895
2032
|
this._emitOrigin(elementInfo.subject, null);
|
|
1896
2033
|
}
|
|
1897
2034
|
/**
|
|
2035
|
+
* @private
|
|
1898
2036
|
* @param {?} subject
|
|
1899
2037
|
* @param {?} origin
|
|
1900
2038
|
* @return {?}
|
|
@@ -1903,31 +2041,39 @@ class FocusMonitor {
|
|
|
1903
2041
|
this._ngZone.run(() => subject.next(origin));
|
|
1904
2042
|
}
|
|
1905
2043
|
/**
|
|
2044
|
+
* @private
|
|
1906
2045
|
* @return {?}
|
|
1907
2046
|
*/
|
|
1908
2047
|
_incrementMonitoredElementCount() {
|
|
1909
2048
|
// Register global listeners when first element is monitored.
|
|
1910
|
-
if (++this._monitoredElementCount == 1) {
|
|
1911
|
-
|
|
2049
|
+
if (++this._monitoredElementCount == 1 && this._platform.isBrowser) {
|
|
2050
|
+
// Note: we listen to events in the capture phase so we
|
|
2051
|
+
// can detect them even if the user stops propagation.
|
|
2052
|
+
this._ngZone.runOutsideAngular(() => {
|
|
2053
|
+
document.addEventListener('keydown', this._documentKeydownListener, captureEventListenerOptions);
|
|
2054
|
+
document.addEventListener('mousedown', this._documentMousedownListener, captureEventListenerOptions);
|
|
2055
|
+
document.addEventListener('touchstart', this._documentTouchstartListener, captureEventListenerOptions);
|
|
2056
|
+
window.addEventListener('focus', this._windowFocusListener);
|
|
2057
|
+
});
|
|
1912
2058
|
}
|
|
1913
2059
|
}
|
|
1914
2060
|
/**
|
|
2061
|
+
* @private
|
|
1915
2062
|
* @return {?}
|
|
1916
2063
|
*/
|
|
1917
2064
|
_decrementMonitoredElementCount() {
|
|
1918
2065
|
// Unregister global listeners when last element is unmonitored.
|
|
1919
2066
|
if (!--this._monitoredElementCount) {
|
|
1920
|
-
this.
|
|
1921
|
-
this.
|
|
2067
|
+
document.removeEventListener('keydown', this._documentKeydownListener, captureEventListenerOptions);
|
|
2068
|
+
document.removeEventListener('mousedown', this._documentMousedownListener, captureEventListenerOptions);
|
|
2069
|
+
document.removeEventListener('touchstart', this._documentTouchstartListener, captureEventListenerOptions);
|
|
2070
|
+
window.removeEventListener('focus', this._windowFocusListener);
|
|
2071
|
+
// Clear timeouts for all potentially pending timeouts to prevent the leaks.
|
|
2072
|
+
clearTimeout(this._windowFocusTimeoutId);
|
|
2073
|
+
clearTimeout(this._touchTimeoutId);
|
|
2074
|
+
clearTimeout(this._originTimeoutId);
|
|
1922
2075
|
}
|
|
1923
2076
|
}
|
|
1924
|
-
/**
|
|
1925
|
-
* @param {?} element
|
|
1926
|
-
* @return {?}
|
|
1927
|
-
*/
|
|
1928
|
-
_getNativeElement(element) {
|
|
1929
|
-
return element instanceof ElementRef ? element.nativeElement : element;
|
|
1930
|
-
}
|
|
1931
2077
|
}
|
|
1932
2078
|
FocusMonitor.decorators = [
|
|
1933
2079
|
{ type: Injectable, args: [{ providedIn: 'root' },] },
|
|
@@ -1990,9 +2136,10 @@ CdkMonitorFocus.propDecorators = {
|
|
|
1990
2136
|
function FOCUS_MONITOR_PROVIDER_FACTORY(parentDispatcher, ngZone, platform) {
|
|
1991
2137
|
return parentDispatcher || new FocusMonitor(ngZone, platform);
|
|
1992
2138
|
}
|
|
1993
|
-
/**
|
|
2139
|
+
/**
|
|
1994
2140
|
* \@docs-private \@deprecated \@breaking-change 8.0.0
|
|
1995
|
-
|
|
2141
|
+
* @type {?}
|
|
2142
|
+
*/
|
|
1996
2143
|
const FOCUS_MONITOR_PROVIDER = {
|
|
1997
2144
|
// If there is already a FocusMonitor available, use that. Otherwise, provide a new one.
|
|
1998
2145
|
provide: FocusMonitor,
|
|
@@ -2002,7 +2149,7 @@ const FOCUS_MONITOR_PROVIDER = {
|
|
|
2002
2149
|
|
|
2003
2150
|
/**
|
|
2004
2151
|
* @fileoverview added by tsickle
|
|
2005
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
2152
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2006
2153
|
*/
|
|
2007
2154
|
|
|
2008
2155
|
/**
|
|
@@ -2020,7 +2167,7 @@ function isFakeMousedownFromScreenReader(event) {
|
|
|
2020
2167
|
|
|
2021
2168
|
/**
|
|
2022
2169
|
* @fileoverview added by tsickle
|
|
2023
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
2170
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2024
2171
|
*/
|
|
2025
2172
|
class A11yModule {
|
|
2026
2173
|
}
|
|
@@ -2034,12 +2181,12 @@ A11yModule.decorators = [
|
|
|
2034
2181
|
|
|
2035
2182
|
/**
|
|
2036
2183
|
* @fileoverview added by tsickle
|
|
2037
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
2184
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2038
2185
|
*/
|
|
2039
2186
|
|
|
2040
2187
|
/**
|
|
2041
2188
|
* @fileoverview added by tsickle
|
|
2042
|
-
* @suppress {checkTypes,extraRequire,uselessCode} checked by tsc
|
|
2189
|
+
* @suppress {checkTypes,extraRequire,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
|
|
2043
2190
|
*/
|
|
2044
2191
|
|
|
2045
2192
|
export { ARIA_DESCRIBER_PROVIDER_FACTORY, MESSAGES_CONTAINER_ID, CDK_DESCRIBEDBY_ID_PREFIX, CDK_DESCRIBEDBY_HOST_ATTRIBUTE, AriaDescriber, ARIA_DESCRIBER_PROVIDER, ActiveDescendantKeyManager, FocusKeyManager, ListKeyManager, FocusTrap, FocusTrapFactory, CdkTrapFocus, InteractivityChecker, LIVE_ANNOUNCER_PROVIDER_FACTORY, LiveAnnouncer, CdkAriaLive, LIVE_ANNOUNCER_PROVIDER, LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY, LIVE_ANNOUNCER_ELEMENT_TOKEN, FOCUS_MONITOR_PROVIDER_FACTORY, TOUCH_BUFFER_MS, FocusMonitor, CdkMonitorFocus, FOCUS_MONITOR_PROVIDER, isFakeMousedownFromScreenReader, A11yModule };
|