a11y.es5.js 116 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113
  1. /**
  2. * @license
  3. * Copyright Google LLC All Rights Reserved.
  4. *
  5. * Use of this source code is governed by an MIT-style license that can be
  6. * found in the LICENSE file at https://angular.io/license
  7. */
  8. import { DOCUMENT, CommonModule } from '@angular/common';
  9. import { Inject, Injectable, Optional, SkipSelf, QueryList, Directive, ElementRef, Input, NgZone, isDevMode, InjectionToken, EventEmitter, Output, NgModule, ɵɵdefineInjectable, ɵɵinject } from '@angular/core';
  10. import { Subject, Subscription, of } from 'rxjs';
  11. import { UP_ARROW, DOWN_ARROW, LEFT_ARROW, RIGHT_ARROW, TAB, A, Z, ZERO, NINE, hasModifierKey } from '@angular/cdk/keycodes';
  12. import { debounceTime, filter, map, tap, take } from 'rxjs/operators';
  13. import { __extends } from 'tslib';
  14. import { Platform, normalizePassiveListenerOptions, PlatformModule } from '@angular/cdk/platform';
  15. import { coerceBooleanProperty, coerceElement } from '@angular/cdk/coercion';
  16. import { ContentObserver, ObserversModule } from '@angular/cdk/observers';
  17. /**
  18. * @fileoverview added by tsickle
  19. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  20. */
  21. /**
  22. * IDs are deliminated by an empty space, as per the spec.
  23. * @type {?}
  24. */
  25. var ID_DELIMINATOR = ' ';
  26. /**
  27. * Adds the given ID to the specified ARIA attribute on an element.
  28. * Used for attributes such as aria-labelledby, aria-owns, etc.
  29. * @param {?} el
  30. * @param {?} attr
  31. * @param {?} id
  32. * @return {?}
  33. */
  34. function addAriaReferencedId(el, attr, id) {
  35. /** @type {?} */
  36. var ids = getAriaReferenceIds(el, attr);
  37. if (ids.some((/**
  38. * @param {?} existingId
  39. * @return {?}
  40. */
  41. function (existingId) { return existingId.trim() == id.trim(); }))) {
  42. return;
  43. }
  44. ids.push(id.trim());
  45. el.setAttribute(attr, ids.join(ID_DELIMINATOR));
  46. }
  47. /**
  48. * Removes the given ID from the specified ARIA attribute on an element.
  49. * Used for attributes such as aria-labelledby, aria-owns, etc.
  50. * @param {?} el
  51. * @param {?} attr
  52. * @param {?} id
  53. * @return {?}
  54. */
  55. function removeAriaReferencedId(el, attr, id) {
  56. /** @type {?} */
  57. var ids = getAriaReferenceIds(el, attr);
  58. /** @type {?} */
  59. var filteredIds = ids.filter((/**
  60. * @param {?} val
  61. * @return {?}
  62. */
  63. function (val) { return val != id.trim(); }));
  64. if (filteredIds.length) {
  65. el.setAttribute(attr, filteredIds.join(ID_DELIMINATOR));
  66. }
  67. else {
  68. el.removeAttribute(attr);
  69. }
  70. }
  71. /**
  72. * Gets the list of IDs referenced by the given ARIA attribute on an element.
  73. * Used for attributes such as aria-labelledby, aria-owns, etc.
  74. * @param {?} el
  75. * @param {?} attr
  76. * @return {?}
  77. */
  78. function getAriaReferenceIds(el, attr) {
  79. // Get string array of all individual ids (whitespace deliminated) in the attribute value
  80. return (el.getAttribute(attr) || '').match(/\S+/g) || [];
  81. }
  82. /**
  83. * @fileoverview added by tsickle
  84. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  85. */
  86. /**
  87. * ID used for the body container where all messages are appended.
  88. * @type {?}
  89. */
  90. var MESSAGES_CONTAINER_ID = 'cdk-describedby-message-container';
  91. /**
  92. * ID prefix used for each created message element.
  93. * @type {?}
  94. */
  95. var CDK_DESCRIBEDBY_ID_PREFIX = 'cdk-describedby-message';
  96. /**
  97. * Attribute given to each host element that is described by a message element.
  98. * @type {?}
  99. */
  100. var CDK_DESCRIBEDBY_HOST_ATTRIBUTE = 'cdk-describedby-host';
  101. /**
  102. * Global incremental identifier for each registered message element.
  103. * @type {?}
  104. */
  105. var nextId = 0;
  106. /**
  107. * Global map of all registered message elements that have been placed into the document.
  108. * @type {?}
  109. */
  110. var messageRegistry = new Map();
  111. /**
  112. * Container for all registered messages.
  113. * @type {?}
  114. */
  115. var messagesContainer = null;
  116. /**
  117. * Utility that creates visually hidden elements with a message content. Useful for elements that
  118. * want to use aria-describedby to further describe themselves without adding additional visual
  119. * content.
  120. */
  121. var AriaDescriber = /** @class */ (function () {
  122. function AriaDescriber(_document) {
  123. this._document = _document;
  124. }
  125. /**
  126. * Adds to the host element an aria-describedby reference to a hidden element that contains
  127. * the message. If the same message has already been registered, then it will reuse the created
  128. * message element.
  129. */
  130. /**
  131. * Adds to the host element an aria-describedby reference to a hidden element that contains
  132. * the message. If the same message has already been registered, then it will reuse the created
  133. * message element.
  134. * @param {?} hostElement
  135. * @param {?} message
  136. * @return {?}
  137. */
  138. AriaDescriber.prototype.describe = /**
  139. * Adds to the host element an aria-describedby reference to a hidden element that contains
  140. * the message. If the same message has already been registered, then it will reuse the created
  141. * message element.
  142. * @param {?} hostElement
  143. * @param {?} message
  144. * @return {?}
  145. */
  146. function (hostElement, message) {
  147. if (!this._canBeDescribed(hostElement, message)) {
  148. return;
  149. }
  150. if (typeof message !== 'string') {
  151. // We need to ensure that the element has an ID.
  152. this._setMessageId(message);
  153. messageRegistry.set(message, { messageElement: message, referenceCount: 0 });
  154. }
  155. else if (!messageRegistry.has(message)) {
  156. this._createMessageElement(message);
  157. }
  158. if (!this._isElementDescribedByMessage(hostElement, message)) {
  159. this._addMessageReference(hostElement, message);
  160. }
  161. };
  162. /** Removes the host element's aria-describedby reference to the message element. */
  163. /**
  164. * Removes the host element's aria-describedby reference to the message element.
  165. * @param {?} hostElement
  166. * @param {?} message
  167. * @return {?}
  168. */
  169. AriaDescriber.prototype.removeDescription = /**
  170. * Removes the host element's aria-describedby reference to the message element.
  171. * @param {?} hostElement
  172. * @param {?} message
  173. * @return {?}
  174. */
  175. function (hostElement, message) {
  176. if (!this._isElementNode(hostElement)) {
  177. return;
  178. }
  179. if (this._isElementDescribedByMessage(hostElement, message)) {
  180. this._removeMessageReference(hostElement, message);
  181. }
  182. // If the message is a string, it means that it's one that we created for the
  183. // consumer so we can remove it safely, otherwise we should leave it in place.
  184. if (typeof message === 'string') {
  185. /** @type {?} */
  186. var registeredMessage = messageRegistry.get(message);
  187. if (registeredMessage && registeredMessage.referenceCount === 0) {
  188. this._deleteMessageElement(message);
  189. }
  190. }
  191. if (messagesContainer && messagesContainer.childNodes.length === 0) {
  192. this._deleteMessagesContainer();
  193. }
  194. };
  195. /** Unregisters all created message elements and removes the message container. */
  196. /**
  197. * Unregisters all created message elements and removes the message container.
  198. * @return {?}
  199. */
  200. AriaDescriber.prototype.ngOnDestroy = /**
  201. * Unregisters all created message elements and removes the message container.
  202. * @return {?}
  203. */
  204. function () {
  205. /** @type {?} */
  206. var describedElements = this._document.querySelectorAll("[" + CDK_DESCRIBEDBY_HOST_ATTRIBUTE + "]");
  207. for (var i = 0; i < describedElements.length; i++) {
  208. this._removeCdkDescribedByReferenceIds(describedElements[i]);
  209. describedElements[i].removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
  210. }
  211. if (messagesContainer) {
  212. this._deleteMessagesContainer();
  213. }
  214. messageRegistry.clear();
  215. };
  216. /**
  217. * Creates a new element in the visually hidden message container element with the message
  218. * as its content and adds it to the message registry.
  219. */
  220. /**
  221. * Creates a new element in the visually hidden message container element with the message
  222. * as its content and adds it to the message registry.
  223. * @private
  224. * @param {?} message
  225. * @return {?}
  226. */
  227. AriaDescriber.prototype._createMessageElement = /**
  228. * Creates a new element in the visually hidden message container element with the message
  229. * as its content and adds it to the message registry.
  230. * @private
  231. * @param {?} message
  232. * @return {?}
  233. */
  234. function (message) {
  235. /** @type {?} */
  236. var messageElement = this._document.createElement('div');
  237. this._setMessageId(messageElement);
  238. messageElement.textContent = message;
  239. this._createMessagesContainer();
  240. (/** @type {?} */ (messagesContainer)).appendChild(messageElement);
  241. messageRegistry.set(message, { messageElement: messageElement, referenceCount: 0 });
  242. };
  243. /** Assigns a unique ID to an element, if it doesn't have one already. */
  244. /**
  245. * Assigns a unique ID to an element, if it doesn't have one already.
  246. * @private
  247. * @param {?} element
  248. * @return {?}
  249. */
  250. AriaDescriber.prototype._setMessageId = /**
  251. * Assigns a unique ID to an element, if it doesn't have one already.
  252. * @private
  253. * @param {?} element
  254. * @return {?}
  255. */
  256. function (element) {
  257. if (!element.id) {
  258. element.id = CDK_DESCRIBEDBY_ID_PREFIX + "-" + nextId++;
  259. }
  260. };
  261. /** Deletes the message element from the global messages container. */
  262. /**
  263. * Deletes the message element from the global messages container.
  264. * @private
  265. * @param {?} message
  266. * @return {?}
  267. */
  268. AriaDescriber.prototype._deleteMessageElement = /**
  269. * Deletes the message element from the global messages container.
  270. * @private
  271. * @param {?} message
  272. * @return {?}
  273. */
  274. function (message) {
  275. /** @type {?} */
  276. var registeredMessage = messageRegistry.get(message);
  277. /** @type {?} */
  278. var messageElement = registeredMessage && registeredMessage.messageElement;
  279. if (messagesContainer && messageElement) {
  280. messagesContainer.removeChild(messageElement);
  281. }
  282. messageRegistry.delete(message);
  283. };
  284. /** Creates the global container for all aria-describedby messages. */
  285. /**
  286. * Creates the global container for all aria-describedby messages.
  287. * @private
  288. * @return {?}
  289. */
  290. AriaDescriber.prototype._createMessagesContainer = /**
  291. * Creates the global container for all aria-describedby messages.
  292. * @private
  293. * @return {?}
  294. */
  295. function () {
  296. if (!messagesContainer) {
  297. /** @type {?} */
  298. var preExistingContainer = this._document.getElementById(MESSAGES_CONTAINER_ID);
  299. // When going from the server to the client, we may end up in a situation where there's
  300. // already a container on the page, but we don't have a reference to it. Clear the
  301. // old container so we don't get duplicates. Doing this, instead of emptying the previous
  302. // container, should be slightly faster.
  303. if (preExistingContainer) {
  304. (/** @type {?} */ (preExistingContainer.parentNode)).removeChild(preExistingContainer);
  305. }
  306. messagesContainer = this._document.createElement('div');
  307. messagesContainer.id = MESSAGES_CONTAINER_ID;
  308. messagesContainer.setAttribute('aria-hidden', 'true');
  309. messagesContainer.style.display = 'none';
  310. this._document.body.appendChild(messagesContainer);
  311. }
  312. };
  313. /** Deletes the global messages container. */
  314. /**
  315. * Deletes the global messages container.
  316. * @private
  317. * @return {?}
  318. */
  319. AriaDescriber.prototype._deleteMessagesContainer = /**
  320. * Deletes the global messages container.
  321. * @private
  322. * @return {?}
  323. */
  324. function () {
  325. if (messagesContainer && messagesContainer.parentNode) {
  326. messagesContainer.parentNode.removeChild(messagesContainer);
  327. messagesContainer = null;
  328. }
  329. };
  330. /** Removes all cdk-describedby messages that are hosted through the element. */
  331. /**
  332. * Removes all cdk-describedby messages that are hosted through the element.
  333. * @private
  334. * @param {?} element
  335. * @return {?}
  336. */
  337. AriaDescriber.prototype._removeCdkDescribedByReferenceIds = /**
  338. * Removes all cdk-describedby messages that are hosted through the element.
  339. * @private
  340. * @param {?} element
  341. * @return {?}
  342. */
  343. function (element) {
  344. // Remove all aria-describedby reference IDs that are prefixed by CDK_DESCRIBEDBY_ID_PREFIX
  345. /** @type {?} */
  346. var originalReferenceIds = getAriaReferenceIds(element, 'aria-describedby')
  347. .filter((/**
  348. * @param {?} id
  349. * @return {?}
  350. */
  351. function (id) { return id.indexOf(CDK_DESCRIBEDBY_ID_PREFIX) != 0; }));
  352. element.setAttribute('aria-describedby', originalReferenceIds.join(' '));
  353. };
  354. /**
  355. * Adds a message reference to the element using aria-describedby and increments the registered
  356. * message's reference count.
  357. */
  358. /**
  359. * Adds a message reference to the element using aria-describedby and increments the registered
  360. * message's reference count.
  361. * @private
  362. * @param {?} element
  363. * @param {?} message
  364. * @return {?}
  365. */
  366. AriaDescriber.prototype._addMessageReference = /**
  367. * Adds a message reference to the element using aria-describedby and increments the registered
  368. * message's reference count.
  369. * @private
  370. * @param {?} element
  371. * @param {?} message
  372. * @return {?}
  373. */
  374. function (element, message) {
  375. /** @type {?} */
  376. var registeredMessage = (/** @type {?} */ (messageRegistry.get(message)));
  377. // Add the aria-describedby reference and set the
  378. // describedby_host attribute to mark the element.
  379. addAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
  380. element.setAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE, '');
  381. registeredMessage.referenceCount++;
  382. };
  383. /**
  384. * Removes a message reference from the element using aria-describedby
  385. * and decrements the registered message's reference count.
  386. */
  387. /**
  388. * Removes a message reference from the element using aria-describedby
  389. * and decrements the registered message's reference count.
  390. * @private
  391. * @param {?} element
  392. * @param {?} message
  393. * @return {?}
  394. */
  395. AriaDescriber.prototype._removeMessageReference = /**
  396. * Removes a message reference from the element using aria-describedby
  397. * and decrements the registered message's reference count.
  398. * @private
  399. * @param {?} element
  400. * @param {?} message
  401. * @return {?}
  402. */
  403. function (element, message) {
  404. /** @type {?} */
  405. var registeredMessage = (/** @type {?} */ (messageRegistry.get(message)));
  406. registeredMessage.referenceCount--;
  407. removeAriaReferencedId(element, 'aria-describedby', registeredMessage.messageElement.id);
  408. element.removeAttribute(CDK_DESCRIBEDBY_HOST_ATTRIBUTE);
  409. };
  410. /** Returns true if the element has been described by the provided message ID. */
  411. /**
  412. * Returns true if the element has been described by the provided message ID.
  413. * @private
  414. * @param {?} element
  415. * @param {?} message
  416. * @return {?}
  417. */
  418. AriaDescriber.prototype._isElementDescribedByMessage = /**
  419. * Returns true if the element has been described by the provided message ID.
  420. * @private
  421. * @param {?} element
  422. * @param {?} message
  423. * @return {?}
  424. */
  425. function (element, message) {
  426. /** @type {?} */
  427. var referenceIds = getAriaReferenceIds(element, 'aria-describedby');
  428. /** @type {?} */
  429. var registeredMessage = messageRegistry.get(message);
  430. /** @type {?} */
  431. var messageId = registeredMessage && registeredMessage.messageElement.id;
  432. return !!messageId && referenceIds.indexOf(messageId) != -1;
  433. };
  434. /** Determines whether a message can be described on a particular element. */
  435. /**
  436. * Determines whether a message can be described on a particular element.
  437. * @private
  438. * @param {?} element
  439. * @param {?} message
  440. * @return {?}
  441. */
  442. AriaDescriber.prototype._canBeDescribed = /**
  443. * Determines whether a message can be described on a particular element.
  444. * @private
  445. * @param {?} element
  446. * @param {?} message
  447. * @return {?}
  448. */
  449. function (element, message) {
  450. if (!this._isElementNode(element)) {
  451. return false;
  452. }
  453. if (message && typeof message === 'object') {
  454. // We'd have to make some assumptions about the description element's text, if the consumer
  455. // passed in an element. Assume that if an element is passed in, the consumer has verified
  456. // that it can be used as a description.
  457. return true;
  458. }
  459. /** @type {?} */
  460. var trimmedMessage = message == null ? '' : ("" + message).trim();
  461. /** @type {?} */
  462. var ariaLabel = element.getAttribute('aria-label');
  463. // We shouldn't set descriptions if they're exactly the same as the `aria-label` of the
  464. // element, because screen readers will end up reading out the same text twice in a row.
  465. return trimmedMessage ? (!ariaLabel || ariaLabel.trim() !== trimmedMessage) : false;
  466. };
  467. /** Checks whether a node is an Element node. */
  468. /**
  469. * Checks whether a node is an Element node.
  470. * @private
  471. * @param {?} element
  472. * @return {?}
  473. */
  474. AriaDescriber.prototype._isElementNode = /**
  475. * Checks whether a node is an Element node.
  476. * @private
  477. * @param {?} element
  478. * @return {?}
  479. */
  480. function (element) {
  481. return element.nodeType === this._document.ELEMENT_NODE;
  482. };
  483. AriaDescriber.decorators = [
  484. { type: Injectable, args: [{ providedIn: 'root' },] },
  485. ];
  486. /** @nocollapse */
  487. AriaDescriber.ctorParameters = function () { return [
  488. { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
  489. ]; };
  490. /** @nocollapse */ AriaDescriber.ngInjectableDef = ɵɵdefineInjectable({ factory: function AriaDescriber_Factory() { return new AriaDescriber(ɵɵinject(DOCUMENT)); }, token: AriaDescriber, providedIn: "root" });
  491. return AriaDescriber;
  492. }());
  493. /**
  494. * \@docs-private \@deprecated \@breaking-change 8.0.0
  495. * @param {?} parentDispatcher
  496. * @param {?} _document
  497. * @return {?}
  498. */
  499. function ARIA_DESCRIBER_PROVIDER_FACTORY(parentDispatcher, _document) {
  500. return parentDispatcher || new AriaDescriber(_document);
  501. }
  502. /**
  503. * \@docs-private \@deprecated \@breaking-change 8.0.0
  504. * @type {?}
  505. */
  506. var ARIA_DESCRIBER_PROVIDER = {
  507. // If there is already an AriaDescriber available, use that. Otherwise, provide a new one.
  508. provide: AriaDescriber,
  509. deps: [
  510. [new Optional(), new SkipSelf(), AriaDescriber],
  511. (/** @type {?} */ (DOCUMENT))
  512. ],
  513. useFactory: ARIA_DESCRIBER_PROVIDER_FACTORY
  514. };
  515. /**
  516. * @fileoverview added by tsickle
  517. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  518. */
  519. /**
  520. * This class manages keyboard events for selectable lists. If you pass it a query list
  521. * of items, it will set the active item correctly when arrow events occur.
  522. * @template T
  523. */
  524. var /**
  525. * This class manages keyboard events for selectable lists. If you pass it a query list
  526. * of items, it will set the active item correctly when arrow events occur.
  527. * @template T
  528. */
  529. ListKeyManager = /** @class */ (function () {
  530. function ListKeyManager(_items) {
  531. var _this = this;
  532. this._items = _items;
  533. this._activeItemIndex = -1;
  534. this._activeItem = null;
  535. this._wrap = false;
  536. this._letterKeyStream = new Subject();
  537. this._typeaheadSubscription = Subscription.EMPTY;
  538. this._vertical = true;
  539. this._allowedModifierKeys = [];
  540. /**
  541. * Predicate function that can be used to check whether an item should be skipped
  542. * by the key manager. By default, disabled items are skipped.
  543. */
  544. this._skipPredicateFn = (/**
  545. * @param {?} item
  546. * @return {?}
  547. */
  548. function (item) { return item.disabled; });
  549. // Buffer for the letters that the user has pressed when the typeahead option is turned on.
  550. this._pressedLetters = [];
  551. /**
  552. * Stream that emits any time the TAB key is pressed, so components can react
  553. * when focus is shifted off of the list.
  554. */
  555. this.tabOut = new Subject();
  556. /**
  557. * Stream that emits whenever the active item of the list manager changes.
  558. */
  559. this.change = new Subject();
  560. // We allow for the items to be an array because, in some cases, the consumer may
  561. // not have access to a QueryList of the items they want to manage (e.g. when the
  562. // items aren't being collected via `ViewChildren` or `ContentChildren`).
  563. if (_items instanceof QueryList) {
  564. _items.changes.subscribe((/**
  565. * @param {?} newItems
  566. * @return {?}
  567. */
  568. function (newItems) {
  569. if (_this._activeItem) {
  570. /** @type {?} */
  571. var itemArray = newItems.toArray();
  572. /** @type {?} */
  573. var newIndex = itemArray.indexOf(_this._activeItem);
  574. if (newIndex > -1 && newIndex !== _this._activeItemIndex) {
  575. _this._activeItemIndex = newIndex;
  576. }
  577. }
  578. }));
  579. }
  580. }
  581. /**
  582. * Sets the predicate function that determines which items should be skipped by the
  583. * list key manager.
  584. * @param predicate Function that determines whether the given item should be skipped.
  585. */
  586. /**
  587. * Sets the predicate function that determines which items should be skipped by the
  588. * list key manager.
  589. * @template THIS
  590. * @this {THIS}
  591. * @param {?} predicate Function that determines whether the given item should be skipped.
  592. * @return {THIS}
  593. */
  594. ListKeyManager.prototype.skipPredicate = /**
  595. * Sets the predicate function that determines which items should be skipped by the
  596. * list key manager.
  597. * @template THIS
  598. * @this {THIS}
  599. * @param {?} predicate Function that determines whether the given item should be skipped.
  600. * @return {THIS}
  601. */
  602. function (predicate) {
  603. (/** @type {?} */ (this))._skipPredicateFn = predicate;
  604. return (/** @type {?} */ (this));
  605. };
  606. /**
  607. * Configures wrapping mode, which determines whether the active item will wrap to
  608. * the other end of list when there are no more items in the given direction.
  609. * @param shouldWrap Whether the list should wrap when reaching the end.
  610. */
  611. /**
  612. * Configures wrapping mode, which determines whether the active item will wrap to
  613. * the other end of list when there are no more items in the given direction.
  614. * @template THIS
  615. * @this {THIS}
  616. * @param {?=} shouldWrap Whether the list should wrap when reaching the end.
  617. * @return {THIS}
  618. */
  619. ListKeyManager.prototype.withWrap = /**
  620. * Configures wrapping mode, which determines whether the active item will wrap to
  621. * the other end of list when there are no more items in the given direction.
  622. * @template THIS
  623. * @this {THIS}
  624. * @param {?=} shouldWrap Whether the list should wrap when reaching the end.
  625. * @return {THIS}
  626. */
  627. function (shouldWrap) {
  628. if (shouldWrap === void 0) { shouldWrap = true; }
  629. (/** @type {?} */ (this))._wrap = shouldWrap;
  630. return (/** @type {?} */ (this));
  631. };
  632. /**
  633. * Configures whether the key manager should be able to move the selection vertically.
  634. * @param enabled Whether vertical selection should be enabled.
  635. */
  636. /**
  637. * Configures whether the key manager should be able to move the selection vertically.
  638. * @template THIS
  639. * @this {THIS}
  640. * @param {?=} enabled Whether vertical selection should be enabled.
  641. * @return {THIS}
  642. */
  643. ListKeyManager.prototype.withVerticalOrientation = /**
  644. * Configures whether the key manager should be able to move the selection vertically.
  645. * @template THIS
  646. * @this {THIS}
  647. * @param {?=} enabled Whether vertical selection should be enabled.
  648. * @return {THIS}
  649. */
  650. function (enabled) {
  651. if (enabled === void 0) { enabled = true; }
  652. (/** @type {?} */ (this))._vertical = enabled;
  653. return (/** @type {?} */ (this));
  654. };
  655. /**
  656. * Configures the key manager to move the selection horizontally.
  657. * Passing in `null` will disable horizontal movement.
  658. * @param direction Direction in which the selection can be moved.
  659. */
  660. /**
  661. * Configures the key manager to move the selection horizontally.
  662. * Passing in `null` will disable horizontal movement.
  663. * @template THIS
  664. * @this {THIS}
  665. * @param {?} direction Direction in which the selection can be moved.
  666. * @return {THIS}
  667. */
  668. ListKeyManager.prototype.withHorizontalOrientation = /**
  669. * Configures the key manager to move the selection horizontally.
  670. * Passing in `null` will disable horizontal movement.
  671. * @template THIS
  672. * @this {THIS}
  673. * @param {?} direction Direction in which the selection can be moved.
  674. * @return {THIS}
  675. */
  676. function (direction) {
  677. (/** @type {?} */ (this))._horizontal = direction;
  678. return (/** @type {?} */ (this));
  679. };
  680. /**
  681. * Modifier keys which are allowed to be held down and whose default actions will be prevented
  682. * as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.
  683. */
  684. /**
  685. * Modifier keys which are allowed to be held down and whose default actions will be prevented
  686. * as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.
  687. * @template THIS
  688. * @this {THIS}
  689. * @param {?} keys
  690. * @return {THIS}
  691. */
  692. ListKeyManager.prototype.withAllowedModifierKeys = /**
  693. * Modifier keys which are allowed to be held down and whose default actions will be prevented
  694. * as the user is pressing the arrow keys. Defaults to not allowing any modifier keys.
  695. * @template THIS
  696. * @this {THIS}
  697. * @param {?} keys
  698. * @return {THIS}
  699. */
  700. function (keys) {
  701. (/** @type {?} */ (this))._allowedModifierKeys = keys;
  702. return (/** @type {?} */ (this));
  703. };
  704. /**
  705. * Turns on typeahead mode which allows users to set the active item by typing.
  706. * @param debounceInterval Time to wait after the last keystroke before setting the active item.
  707. */
  708. /**
  709. * Turns on typeahead mode which allows users to set the active item by typing.
  710. * @template THIS
  711. * @this {THIS}
  712. * @param {?=} debounceInterval Time to wait after the last keystroke before setting the active item.
  713. * @return {THIS}
  714. */
  715. ListKeyManager.prototype.withTypeAhead = /**
  716. * Turns on typeahead mode which allows users to set the active item by typing.
  717. * @template THIS
  718. * @this {THIS}
  719. * @param {?=} debounceInterval Time to wait after the last keystroke before setting the active item.
  720. * @return {THIS}
  721. */
  722. function (debounceInterval) {
  723. var _this = this;
  724. if (debounceInterval === void 0) { debounceInterval = 200; }
  725. if ((/** @type {?} */ (this))._items.length && (/** @type {?} */ (this))._items.some((/**
  726. * @param {?} item
  727. * @return {?}
  728. */
  729. function (item) { return typeof item.getLabel !== 'function'; }))) {
  730. throw Error('ListKeyManager items in typeahead mode must implement the `getLabel` method.');
  731. }
  732. (/** @type {?} */ (this))._typeaheadSubscription.unsubscribe();
  733. // Debounce the presses of non-navigational keys, collect the ones that correspond to letters
  734. // and convert those letters back into a string. Afterwards find the first item that starts
  735. // with that string and select it.
  736. (/** @type {?} */ (this))._typeaheadSubscription = (/** @type {?} */ (this))._letterKeyStream.pipe(tap((/**
  737. * @param {?} keyCode
  738. * @return {?}
  739. */
  740. function (keyCode) { return (/** @type {?} */ (_this))._pressedLetters.push(keyCode); })), debounceTime(debounceInterval), filter((/**
  741. * @return {?}
  742. */
  743. function () { return (/** @type {?} */ (_this))._pressedLetters.length > 0; })), map((/**
  744. * @return {?}
  745. */
  746. function () { return (/** @type {?} */ (_this))._pressedLetters.join(''); }))).subscribe((/**
  747. * @param {?} inputString
  748. * @return {?}
  749. */
  750. function (inputString) {
  751. /** @type {?} */
  752. var items = (/** @type {?} */ (_this))._getItemsArray();
  753. // Start at 1 because we want to start searching at the item immediately
  754. // following the current active item.
  755. for (var i = 1; i < items.length + 1; i++) {
  756. /** @type {?} */
  757. var index = ((/** @type {?} */ (_this))._activeItemIndex + i) % items.length;
  758. /** @type {?} */
  759. var item = items[index];
  760. if (!(/** @type {?} */ (_this))._skipPredicateFn(item) &&
  761. (/** @type {?} */ (item.getLabel))().toUpperCase().trim().indexOf(inputString) === 0) {
  762. (/** @type {?} */ (_this)).setActiveItem(index);
  763. break;
  764. }
  765. }
  766. (/** @type {?} */ (_this))._pressedLetters = [];
  767. }));
  768. return (/** @type {?} */ (this));
  769. };
  770. /**
  771. * @param {?} item
  772. * @return {?}
  773. */
  774. ListKeyManager.prototype.setActiveItem = /**
  775. * @param {?} item
  776. * @return {?}
  777. */
  778. function (item) {
  779. /** @type {?} */
  780. var previousIndex = this._activeItemIndex;
  781. this.updateActiveItem(item);
  782. if (this._activeItemIndex !== previousIndex) {
  783. this.change.next(this._activeItemIndex);
  784. }
  785. };
  786. /**
  787. * Sets the active item depending on the key event passed in.
  788. * @param event Keyboard event to be used for determining which element should be active.
  789. */
  790. /**
  791. * Sets the active item depending on the key event passed in.
  792. * @param {?} event Keyboard event to be used for determining which element should be active.
  793. * @return {?}
  794. */
  795. ListKeyManager.prototype.onKeydown = /**
  796. * Sets the active item depending on the key event passed in.
  797. * @param {?} event Keyboard event to be used for determining which element should be active.
  798. * @return {?}
  799. */
  800. function (event) {
  801. var _this = this;
  802. /** @type {?} */
  803. var keyCode = event.keyCode;
  804. /** @type {?} */
  805. var modifiers = ['altKey', 'ctrlKey', 'metaKey', 'shiftKey'];
  806. /** @type {?} */
  807. var isModifierAllowed = modifiers.every((/**
  808. * @param {?} modifier
  809. * @return {?}
  810. */
  811. function (modifier) {
  812. return !event[modifier] || _this._allowedModifierKeys.indexOf(modifier) > -1;
  813. }));
  814. switch (keyCode) {
  815. case TAB:
  816. this.tabOut.next();
  817. return;
  818. case DOWN_ARROW:
  819. if (this._vertical && isModifierAllowed) {
  820. this.setNextItemActive();
  821. break;
  822. }
  823. else {
  824. return;
  825. }
  826. case UP_ARROW:
  827. if (this._vertical && isModifierAllowed) {
  828. this.setPreviousItemActive();
  829. break;
  830. }
  831. else {
  832. return;
  833. }
  834. case RIGHT_ARROW:
  835. if (this._horizontal && isModifierAllowed) {
  836. this._horizontal === 'rtl' ? this.setPreviousItemActive() : this.setNextItemActive();
  837. break;
  838. }
  839. else {
  840. return;
  841. }
  842. case LEFT_ARROW:
  843. if (this._horizontal && isModifierAllowed) {
  844. this._horizontal === 'rtl' ? this.setNextItemActive() : this.setPreviousItemActive();
  845. break;
  846. }
  847. else {
  848. return;
  849. }
  850. default:
  851. if (isModifierAllowed || hasModifierKey(event, 'shiftKey')) {
  852. // Attempt to use the `event.key` which also maps it to the user's keyboard language,
  853. // otherwise fall back to resolving alphanumeric characters via the keyCode.
  854. if (event.key && event.key.length === 1) {
  855. this._letterKeyStream.next(event.key.toLocaleUpperCase());
  856. }
  857. else if ((keyCode >= A && keyCode <= Z) || (keyCode >= ZERO && keyCode <= NINE)) {
  858. this._letterKeyStream.next(String.fromCharCode(keyCode));
  859. }
  860. }
  861. // Note that we return here, in order to avoid preventing
  862. // the default action of non-navigational keys.
  863. return;
  864. }
  865. this._pressedLetters = [];
  866. event.preventDefault();
  867. };
  868. Object.defineProperty(ListKeyManager.prototype, "activeItemIndex", {
  869. /** Index of the currently active item. */
  870. get: /**
  871. * Index of the currently active item.
  872. * @return {?}
  873. */
  874. function () {
  875. return this._activeItemIndex;
  876. },
  877. enumerable: true,
  878. configurable: true
  879. });
  880. Object.defineProperty(ListKeyManager.prototype, "activeItem", {
  881. /** The active item. */
  882. get: /**
  883. * The active item.
  884. * @return {?}
  885. */
  886. function () {
  887. return this._activeItem;
  888. },
  889. enumerable: true,
  890. configurable: true
  891. });
  892. /** Sets the active item to the first enabled item in the list. */
  893. /**
  894. * Sets the active item to the first enabled item in the list.
  895. * @return {?}
  896. */
  897. ListKeyManager.prototype.setFirstItemActive = /**
  898. * Sets the active item to the first enabled item in the list.
  899. * @return {?}
  900. */
  901. function () {
  902. this._setActiveItemByIndex(0, 1);
  903. };
  904. /** Sets the active item to the last enabled item in the list. */
  905. /**
  906. * Sets the active item to the last enabled item in the list.
  907. * @return {?}
  908. */
  909. ListKeyManager.prototype.setLastItemActive = /**
  910. * Sets the active item to the last enabled item in the list.
  911. * @return {?}
  912. */
  913. function () {
  914. this._setActiveItemByIndex(this._items.length - 1, -1);
  915. };
  916. /** Sets the active item to the next enabled item in the list. */
  917. /**
  918. * Sets the active item to the next enabled item in the list.
  919. * @return {?}
  920. */
  921. ListKeyManager.prototype.setNextItemActive = /**
  922. * Sets the active item to the next enabled item in the list.
  923. * @return {?}
  924. */
  925. function () {
  926. this._activeItemIndex < 0 ? this.setFirstItemActive() : this._setActiveItemByDelta(1);
  927. };
  928. /** Sets the active item to a previous enabled item in the list. */
  929. /**
  930. * Sets the active item to a previous enabled item in the list.
  931. * @return {?}
  932. */
  933. ListKeyManager.prototype.setPreviousItemActive = /**
  934. * Sets the active item to a previous enabled item in the list.
  935. * @return {?}
  936. */
  937. function () {
  938. this._activeItemIndex < 0 && this._wrap ? this.setLastItemActive()
  939. : this._setActiveItemByDelta(-1);
  940. };
  941. /**
  942. * @param {?} item
  943. * @return {?}
  944. */
  945. ListKeyManager.prototype.updateActiveItem = /**
  946. * @param {?} item
  947. * @return {?}
  948. */
  949. function (item) {
  950. /** @type {?} */
  951. var itemArray = this._getItemsArray();
  952. /** @type {?} */
  953. var index = typeof item === 'number' ? item : itemArray.indexOf(item);
  954. /** @type {?} */
  955. var activeItem = itemArray[index];
  956. // Explicitly check for `null` and `undefined` because other falsy values are valid.
  957. this._activeItem = activeItem == null ? null : activeItem;
  958. this._activeItemIndex = index;
  959. };
  960. /**
  961. * Allows setting of the activeItemIndex without any other effects.
  962. * @param index The new activeItemIndex.
  963. * @deprecated Use `updateActiveItem` instead.
  964. * @breaking-change 8.0.0
  965. */
  966. /**
  967. * Allows setting of the activeItemIndex without any other effects.
  968. * @deprecated Use `updateActiveItem` instead.
  969. * \@breaking-change 8.0.0
  970. * @param {?} index The new activeItemIndex.
  971. * @return {?}
  972. */
  973. ListKeyManager.prototype.updateActiveItemIndex = /**
  974. * Allows setting of the activeItemIndex without any other effects.
  975. * @deprecated Use `updateActiveItem` instead.
  976. * \@breaking-change 8.0.0
  977. * @param {?} index The new activeItemIndex.
  978. * @return {?}
  979. */
  980. function (index) {
  981. this.updateActiveItem(index);
  982. };
  983. /**
  984. * This method sets the active item, given a list of items and the delta between the
  985. * currently active item and the new active item. It will calculate differently
  986. * depending on whether wrap mode is turned on.
  987. */
  988. /**
  989. * This method sets the active item, given a list of items and the delta between the
  990. * currently active item and the new active item. It will calculate differently
  991. * depending on whether wrap mode is turned on.
  992. * @private
  993. * @param {?} delta
  994. * @return {?}
  995. */
  996. ListKeyManager.prototype._setActiveItemByDelta = /**
  997. * This method sets the active item, given a list of items and the delta between the
  998. * currently active item and the new active item. It will calculate differently
  999. * depending on whether wrap mode is turned on.
  1000. * @private
  1001. * @param {?} delta
  1002. * @return {?}
  1003. */
  1004. function (delta) {
  1005. this._wrap ? this._setActiveInWrapMode(delta) : this._setActiveInDefaultMode(delta);
  1006. };
  1007. /**
  1008. * Sets the active item properly given "wrap" mode. In other words, it will continue to move
  1009. * down the list until it finds an item that is not disabled, and it will wrap if it
  1010. * encounters either end of the list.
  1011. */
  1012. /**
  1013. * Sets the active item properly given "wrap" mode. In other words, it will continue to move
  1014. * down the list until it finds an item that is not disabled, and it will wrap if it
  1015. * encounters either end of the list.
  1016. * @private
  1017. * @param {?} delta
  1018. * @return {?}
  1019. */
  1020. ListKeyManager.prototype._setActiveInWrapMode = /**
  1021. * Sets the active item properly given "wrap" mode. In other words, it will continue to move
  1022. * down the list until it finds an item that is not disabled, and it will wrap if it
  1023. * encounters either end of the list.
  1024. * @private
  1025. * @param {?} delta
  1026. * @return {?}
  1027. */
  1028. function (delta) {
  1029. /** @type {?} */
  1030. var items = this._getItemsArray();
  1031. for (var i = 1; i <= items.length; i++) {
  1032. /** @type {?} */
  1033. var index = (this._activeItemIndex + (delta * i) + items.length) % items.length;
  1034. /** @type {?} */
  1035. var item = items[index];
  1036. if (!this._skipPredicateFn(item)) {
  1037. this.setActiveItem(index);
  1038. return;
  1039. }
  1040. }
  1041. };
  1042. /**
  1043. * Sets the active item properly given the default mode. In other words, it will
  1044. * continue to move down the list until it finds an item that is not disabled. If
  1045. * it encounters either end of the list, it will stop and not wrap.
  1046. */
  1047. /**
  1048. * Sets the active item properly given the default mode. In other words, it will
  1049. * continue to move down the list until it finds an item that is not disabled. If
  1050. * it encounters either end of the list, it will stop and not wrap.
  1051. * @private
  1052. * @param {?} delta
  1053. * @return {?}
  1054. */
  1055. ListKeyManager.prototype._setActiveInDefaultMode = /**
  1056. * Sets the active item properly given the default mode. In other words, it will
  1057. * continue to move down the list until it finds an item that is not disabled. If
  1058. * it encounters either end of the list, it will stop and not wrap.
  1059. * @private
  1060. * @param {?} delta
  1061. * @return {?}
  1062. */
  1063. function (delta) {
  1064. this._setActiveItemByIndex(this._activeItemIndex + delta, delta);
  1065. };
  1066. /**
  1067. * Sets the active item to the first enabled item starting at the index specified. If the
  1068. * item is disabled, it will move in the fallbackDelta direction until it either
  1069. * finds an enabled item or encounters the end of the list.
  1070. */
  1071. /**
  1072. * Sets the active item to the first enabled item starting at the index specified. If the
  1073. * item is disabled, it will move in the fallbackDelta direction until it either
  1074. * finds an enabled item or encounters the end of the list.
  1075. * @private
  1076. * @param {?} index
  1077. * @param {?} fallbackDelta
  1078. * @return {?}
  1079. */
  1080. ListKeyManager.prototype._setActiveItemByIndex = /**
  1081. * Sets the active item to the first enabled item starting at the index specified. If the
  1082. * item is disabled, it will move in the fallbackDelta direction until it either
  1083. * finds an enabled item or encounters the end of the list.
  1084. * @private
  1085. * @param {?} index
  1086. * @param {?} fallbackDelta
  1087. * @return {?}
  1088. */
  1089. function (index, fallbackDelta) {
  1090. /** @type {?} */
  1091. var items = this._getItemsArray();
  1092. if (!items[index]) {
  1093. return;
  1094. }
  1095. while (this._skipPredicateFn(items[index])) {
  1096. index += fallbackDelta;
  1097. if (!items[index]) {
  1098. return;
  1099. }
  1100. }
  1101. this.setActiveItem(index);
  1102. };
  1103. /** Returns the items as an array. */
  1104. /**
  1105. * Returns the items as an array.
  1106. * @private
  1107. * @return {?}
  1108. */
  1109. ListKeyManager.prototype._getItemsArray = /**
  1110. * Returns the items as an array.
  1111. * @private
  1112. * @return {?}
  1113. */
  1114. function () {
  1115. return this._items instanceof QueryList ? this._items.toArray() : this._items;
  1116. };
  1117. return ListKeyManager;
  1118. }());
  1119. /**
  1120. * @fileoverview added by tsickle
  1121. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  1122. */
  1123. /**
  1124. * @template T
  1125. */
  1126. var /**
  1127. * @template T
  1128. */
  1129. ActiveDescendantKeyManager = /** @class */ (function (_super) {
  1130. __extends(ActiveDescendantKeyManager, _super);
  1131. function ActiveDescendantKeyManager() {
  1132. return _super !== null && _super.apply(this, arguments) || this;
  1133. }
  1134. /**
  1135. * @param {?} index
  1136. * @return {?}
  1137. */
  1138. ActiveDescendantKeyManager.prototype.setActiveItem = /**
  1139. * @param {?} index
  1140. * @return {?}
  1141. */
  1142. function (index) {
  1143. if (this.activeItem) {
  1144. this.activeItem.setInactiveStyles();
  1145. }
  1146. _super.prototype.setActiveItem.call(this, index);
  1147. if (this.activeItem) {
  1148. this.activeItem.setActiveStyles();
  1149. }
  1150. };
  1151. return ActiveDescendantKeyManager;
  1152. }(ListKeyManager));
  1153. /**
  1154. * @fileoverview added by tsickle
  1155. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  1156. */
  1157. /**
  1158. * @template T
  1159. */
  1160. var /**
  1161. * @template T
  1162. */
  1163. FocusKeyManager = /** @class */ (function (_super) {
  1164. __extends(FocusKeyManager, _super);
  1165. function FocusKeyManager() {
  1166. var _this = _super !== null && _super.apply(this, arguments) || this;
  1167. _this._origin = 'program';
  1168. return _this;
  1169. }
  1170. /**
  1171. * Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.
  1172. * @param origin Focus origin to be used when focusing items.
  1173. */
  1174. /**
  1175. * Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.
  1176. * @template THIS
  1177. * @this {THIS}
  1178. * @param {?} origin Focus origin to be used when focusing items.
  1179. * @return {THIS}
  1180. */
  1181. FocusKeyManager.prototype.setFocusOrigin = /**
  1182. * Sets the focus origin that will be passed in to the items for any subsequent `focus` calls.
  1183. * @template THIS
  1184. * @this {THIS}
  1185. * @param {?} origin Focus origin to be used when focusing items.
  1186. * @return {THIS}
  1187. */
  1188. function (origin) {
  1189. (/** @type {?} */ (this))._origin = origin;
  1190. return (/** @type {?} */ (this));
  1191. };
  1192. /**
  1193. * @param {?} item
  1194. * @return {?}
  1195. */
  1196. FocusKeyManager.prototype.setActiveItem = /**
  1197. * @param {?} item
  1198. * @return {?}
  1199. */
  1200. function (item) {
  1201. _super.prototype.setActiveItem.call(this, item);
  1202. if (this.activeItem) {
  1203. this.activeItem.focus(this._origin);
  1204. }
  1205. };
  1206. return FocusKeyManager;
  1207. }(ListKeyManager));
  1208. /**
  1209. * @fileoverview added by tsickle
  1210. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  1211. */
  1212. // The InteractivityChecker leans heavily on the ally.js accessibility utilities.
  1213. // Methods like `isTabbable` are only covering specific edge-cases for the browsers which are
  1214. // supported.
  1215. /**
  1216. * Utility for checking the interactivity of an element, such as whether is is focusable or
  1217. * tabbable.
  1218. */
  1219. var InteractivityChecker = /** @class */ (function () {
  1220. function InteractivityChecker(_platform) {
  1221. this._platform = _platform;
  1222. }
  1223. /**
  1224. * Gets whether an element is disabled.
  1225. *
  1226. * @param element Element to be checked.
  1227. * @returns Whether the element is disabled.
  1228. */
  1229. /**
  1230. * Gets whether an element is disabled.
  1231. *
  1232. * @param {?} element Element to be checked.
  1233. * @return {?} Whether the element is disabled.
  1234. */
  1235. InteractivityChecker.prototype.isDisabled = /**
  1236. * Gets whether an element is disabled.
  1237. *
  1238. * @param {?} element Element to be checked.
  1239. * @return {?} Whether the element is disabled.
  1240. */
  1241. function (element) {
  1242. // This does not capture some cases, such as a non-form control with a disabled attribute or
  1243. // a form control inside of a disabled form, but should capture the most common cases.
  1244. return element.hasAttribute('disabled');
  1245. };
  1246. /**
  1247. * Gets whether an element is visible for the purposes of interactivity.
  1248. *
  1249. * This will capture states like `display: none` and `visibility: hidden`, but not things like
  1250. * being clipped by an `overflow: hidden` parent or being outside the viewport.
  1251. *
  1252. * @returns Whether the element is visible.
  1253. */
  1254. /**
  1255. * Gets whether an element is visible for the purposes of interactivity.
  1256. *
  1257. * This will capture states like `display: none` and `visibility: hidden`, but not things like
  1258. * being clipped by an `overflow: hidden` parent or being outside the viewport.
  1259. *
  1260. * @param {?} element
  1261. * @return {?} Whether the element is visible.
  1262. */
  1263. InteractivityChecker.prototype.isVisible = /**
  1264. * Gets whether an element is visible for the purposes of interactivity.
  1265. *
  1266. * This will capture states like `display: none` and `visibility: hidden`, but not things like
  1267. * being clipped by an `overflow: hidden` parent or being outside the viewport.
  1268. *
  1269. * @param {?} element
  1270. * @return {?} Whether the element is visible.
  1271. */
  1272. function (element) {
  1273. return hasGeometry(element) && getComputedStyle(element).visibility === 'visible';
  1274. };
  1275. /**
  1276. * Gets whether an element can be reached via Tab key.
  1277. * Assumes that the element has already been checked with isFocusable.
  1278. *
  1279. * @param element Element to be checked.
  1280. * @returns Whether the element is tabbable.
  1281. */
  1282. /**
  1283. * Gets whether an element can be reached via Tab key.
  1284. * Assumes that the element has already been checked with isFocusable.
  1285. *
  1286. * @param {?} element Element to be checked.
  1287. * @return {?} Whether the element is tabbable.
  1288. */
  1289. InteractivityChecker.prototype.isTabbable = /**
  1290. * Gets whether an element can be reached via Tab key.
  1291. * Assumes that the element has already been checked with isFocusable.
  1292. *
  1293. * @param {?} element Element to be checked.
  1294. * @return {?} Whether the element is tabbable.
  1295. */
  1296. function (element) {
  1297. // Nothing is tabbable on the server 😎
  1298. if (!this._platform.isBrowser) {
  1299. return false;
  1300. }
  1301. /** @type {?} */
  1302. var frameElement = getFrameElement(getWindow(element));
  1303. if (frameElement) {
  1304. /** @type {?} */
  1305. var frameType = frameElement && frameElement.nodeName.toLowerCase();
  1306. // Frame elements inherit their tabindex onto all child elements.
  1307. if (getTabIndexValue(frameElement) === -1) {
  1308. return false;
  1309. }
  1310. // Webkit and Blink consider anything inside of an <object> element as non-tabbable.
  1311. if ((this._platform.BLINK || this._platform.WEBKIT) && frameType === 'object') {
  1312. return false;
  1313. }
  1314. // Webkit and Blink disable tabbing to an element inside of an invisible frame.
  1315. if ((this._platform.BLINK || this._platform.WEBKIT) && !this.isVisible(frameElement)) {
  1316. return false;
  1317. }
  1318. }
  1319. /** @type {?} */
  1320. var nodeName = element.nodeName.toLowerCase();
  1321. /** @type {?} */
  1322. var tabIndexValue = getTabIndexValue(element);
  1323. if (element.hasAttribute('contenteditable')) {
  1324. return tabIndexValue !== -1;
  1325. }
  1326. if (nodeName === 'iframe') {
  1327. // The frames may be tabbable depending on content, but it's not possibly to reliably
  1328. // investigate the content of the frames.
  1329. return false;
  1330. }
  1331. if (nodeName === 'audio') {
  1332. if (!element.hasAttribute('controls')) {
  1333. // By default an <audio> element without the controls enabled is not tabbable.
  1334. return false;
  1335. }
  1336. else if (this._platform.BLINK) {
  1337. // In Blink <audio controls> elements are always tabbable.
  1338. return true;
  1339. }
  1340. }
  1341. if (nodeName === 'video') {
  1342. if (!element.hasAttribute('controls') && this._platform.TRIDENT) {
  1343. // In Trident a <video> element without the controls enabled is not tabbable.
  1344. return false;
  1345. }
  1346. else if (this._platform.BLINK || this._platform.FIREFOX) {
  1347. // In Chrome and Firefox <video controls> elements are always tabbable.
  1348. return true;
  1349. }
  1350. }
  1351. if (nodeName === 'object' && (this._platform.BLINK || this._platform.WEBKIT)) {
  1352. // In all Blink and WebKit based browsers <object> elements are never tabbable.
  1353. return false;
  1354. }
  1355. // In iOS the browser only considers some specific elements as tabbable.
  1356. if (this._platform.WEBKIT && this._platform.IOS && !isPotentiallyTabbableIOS(element)) {
  1357. return false;
  1358. }
  1359. return element.tabIndex >= 0;
  1360. };
  1361. /**
  1362. * Gets whether an element can be focused by the user.
  1363. *
  1364. * @param element Element to be checked.
  1365. * @returns Whether the element is focusable.
  1366. */
  1367. /**
  1368. * Gets whether an element can be focused by the user.
  1369. *
  1370. * @param {?} element Element to be checked.
  1371. * @return {?} Whether the element is focusable.
  1372. */
  1373. InteractivityChecker.prototype.isFocusable = /**
  1374. * Gets whether an element can be focused by the user.
  1375. *
  1376. * @param {?} element Element to be checked.
  1377. * @return {?} Whether the element is focusable.
  1378. */
  1379. function (element) {
  1380. // Perform checks in order of left to most expensive.
  1381. // Again, naive approach that does not capture many edge cases and browser quirks.
  1382. return isPotentiallyFocusable(element) && !this.isDisabled(element) && this.isVisible(element);
  1383. };
  1384. InteractivityChecker.decorators = [
  1385. { type: Injectable, args: [{ providedIn: 'root' },] },
  1386. ];
  1387. /** @nocollapse */
  1388. InteractivityChecker.ctorParameters = function () { return [
  1389. { type: Platform }
  1390. ]; };
  1391. /** @nocollapse */ InteractivityChecker.ngInjectableDef = ɵɵdefineInjectable({ factory: function InteractivityChecker_Factory() { return new InteractivityChecker(ɵɵinject(Platform)); }, token: InteractivityChecker, providedIn: "root" });
  1392. return InteractivityChecker;
  1393. }());
  1394. /**
  1395. * Returns the frame element from a window object. Since browsers like MS Edge throw errors if
  1396. * the frameElement property is being accessed from a different host address, this property
  1397. * should be accessed carefully.
  1398. * @param {?} window
  1399. * @return {?}
  1400. */
  1401. function getFrameElement(window) {
  1402. try {
  1403. return (/** @type {?} */ (window.frameElement));
  1404. }
  1405. catch (_a) {
  1406. return null;
  1407. }
  1408. }
  1409. /**
  1410. * Checks whether the specified element has any geometry / rectangles.
  1411. * @param {?} element
  1412. * @return {?}
  1413. */
  1414. function hasGeometry(element) {
  1415. // Use logic from jQuery to check for an invisible element.
  1416. // See https://github.com/jquery/jquery/blob/master/src/css/hiddenVisibleSelectors.js#L12
  1417. return !!(element.offsetWidth || element.offsetHeight ||
  1418. (typeof element.getClientRects === 'function' && element.getClientRects().length));
  1419. }
  1420. /**
  1421. * Gets whether an element's
  1422. * @param {?} element
  1423. * @return {?}
  1424. */
  1425. function isNativeFormElement(element) {
  1426. /** @type {?} */
  1427. var nodeName = element.nodeName.toLowerCase();
  1428. return nodeName === 'input' ||
  1429. nodeName === 'select' ||
  1430. nodeName === 'button' ||
  1431. nodeName === 'textarea';
  1432. }
  1433. /**
  1434. * Gets whether an element is an `<input type="hidden">`.
  1435. * @param {?} element
  1436. * @return {?}
  1437. */
  1438. function isHiddenInput(element) {
  1439. return isInputElement(element) && element.type == 'hidden';
  1440. }
  1441. /**
  1442. * Gets whether an element is an anchor that has an href attribute.
  1443. * @param {?} element
  1444. * @return {?}
  1445. */
  1446. function isAnchorWithHref(element) {
  1447. return isAnchorElement(element) && element.hasAttribute('href');
  1448. }
  1449. /**
  1450. * Gets whether an element is an input element.
  1451. * @param {?} element
  1452. * @return {?}
  1453. */
  1454. function isInputElement(element) {
  1455. return element.nodeName.toLowerCase() == 'input';
  1456. }
  1457. /**
  1458. * Gets whether an element is an anchor element.
  1459. * @param {?} element
  1460. * @return {?}
  1461. */
  1462. function isAnchorElement(element) {
  1463. return element.nodeName.toLowerCase() == 'a';
  1464. }
  1465. /**
  1466. * Gets whether an element has a valid tabindex.
  1467. * @param {?} element
  1468. * @return {?}
  1469. */
  1470. function hasValidTabIndex(element) {
  1471. if (!element.hasAttribute('tabindex') || element.tabIndex === undefined) {
  1472. return false;
  1473. }
  1474. /** @type {?} */
  1475. var tabIndex = element.getAttribute('tabindex');
  1476. // IE11 parses tabindex="" as the value "-32768"
  1477. if (tabIndex == '-32768') {
  1478. return false;
  1479. }
  1480. return !!(tabIndex && !isNaN(parseInt(tabIndex, 10)));
  1481. }
  1482. /**
  1483. * Returns the parsed tabindex from the element attributes instead of returning the
  1484. * evaluated tabindex from the browsers defaults.
  1485. * @param {?} element
  1486. * @return {?}
  1487. */
  1488. function getTabIndexValue(element) {
  1489. if (!hasValidTabIndex(element)) {
  1490. return null;
  1491. }
  1492. // See browser issue in Gecko https://bugzilla.mozilla.org/show_bug.cgi?id=1128054
  1493. /** @type {?} */
  1494. var tabIndex = parseInt(element.getAttribute('tabindex') || '', 10);
  1495. return isNaN(tabIndex) ? -1 : tabIndex;
  1496. }
  1497. /**
  1498. * Checks whether the specified element is potentially tabbable on iOS
  1499. * @param {?} element
  1500. * @return {?}
  1501. */
  1502. function isPotentiallyTabbableIOS(element) {
  1503. /** @type {?} */
  1504. var nodeName = element.nodeName.toLowerCase();
  1505. /** @type {?} */
  1506. var inputType = nodeName === 'input' && ((/** @type {?} */ (element))).type;
  1507. return inputType === 'text'
  1508. || inputType === 'password'
  1509. || nodeName === 'select'
  1510. || nodeName === 'textarea';
  1511. }
  1512. /**
  1513. * Gets whether an element is potentially focusable without taking current visible/disabled state
  1514. * into account.
  1515. * @param {?} element
  1516. * @return {?}
  1517. */
  1518. function isPotentiallyFocusable(element) {
  1519. // Inputs are potentially focusable *unless* they're type="hidden".
  1520. if (isHiddenInput(element)) {
  1521. return false;
  1522. }
  1523. return isNativeFormElement(element) ||
  1524. isAnchorWithHref(element) ||
  1525. element.hasAttribute('contenteditable') ||
  1526. hasValidTabIndex(element);
  1527. }
  1528. /**
  1529. * Gets the parent window of a DOM node with regards of being inside of an iframe.
  1530. * @param {?} node
  1531. * @return {?}
  1532. */
  1533. function getWindow(node) {
  1534. // ownerDocument is null if `node` itself *is* a document.
  1535. return node.ownerDocument && node.ownerDocument.defaultView || window;
  1536. }
  1537. /**
  1538. * @fileoverview added by tsickle
  1539. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  1540. */
  1541. /**
  1542. * Class that allows for trapping focus within a DOM element.
  1543. *
  1544. * This class currently uses a relatively simple approach to focus trapping.
  1545. * It assumes that the tab order is the same as DOM order, which is not necessarily true.
  1546. * Things like `tabIndex > 0`, flex `order`, and shadow roots can cause to two to misalign.
  1547. */
  1548. var /**
  1549. * Class that allows for trapping focus within a DOM element.
  1550. *
  1551. * This class currently uses a relatively simple approach to focus trapping.
  1552. * It assumes that the tab order is the same as DOM order, which is not necessarily true.
  1553. * Things like `tabIndex > 0`, flex `order`, and shadow roots can cause to two to misalign.
  1554. */
  1555. FocusTrap = /** @class */ (function () {
  1556. function FocusTrap(_element, _checker, _ngZone, _document, deferAnchors) {
  1557. var _this = this;
  1558. if (deferAnchors === void 0) { deferAnchors = false; }
  1559. this._element = _element;
  1560. this._checker = _checker;
  1561. this._ngZone = _ngZone;
  1562. this._document = _document;
  1563. this._hasAttached = false;
  1564. // Event listeners for the anchors. Need to be regular functions so that we can unbind them later.
  1565. this.startAnchorListener = (/**
  1566. * @return {?}
  1567. */
  1568. function () { return _this.focusLastTabbableElement(); });
  1569. this.endAnchorListener = (/**
  1570. * @return {?}
  1571. */
  1572. function () { return _this.focusFirstTabbableElement(); });
  1573. this._enabled = true;
  1574. if (!deferAnchors) {
  1575. this.attachAnchors();
  1576. }
  1577. }
  1578. Object.defineProperty(FocusTrap.prototype, "enabled", {
  1579. /** Whether the focus trap is active. */
  1580. get: /**
  1581. * Whether the focus trap is active.
  1582. * @return {?}
  1583. */
  1584. function () { return this._enabled; },
  1585. set: /**
  1586. * @param {?} value
  1587. * @return {?}
  1588. */
  1589. function (value) {
  1590. this._enabled = value;
  1591. if (this._startAnchor && this._endAnchor) {
  1592. this._toggleAnchorTabIndex(value, this._startAnchor);
  1593. this._toggleAnchorTabIndex(value, this._endAnchor);
  1594. }
  1595. },
  1596. enumerable: true,
  1597. configurable: true
  1598. });
  1599. /** Destroys the focus trap by cleaning up the anchors. */
  1600. /**
  1601. * Destroys the focus trap by cleaning up the anchors.
  1602. * @return {?}
  1603. */
  1604. FocusTrap.prototype.destroy = /**
  1605. * Destroys the focus trap by cleaning up the anchors.
  1606. * @return {?}
  1607. */
  1608. function () {
  1609. /** @type {?} */
  1610. var startAnchor = this._startAnchor;
  1611. /** @type {?} */
  1612. var endAnchor = this._endAnchor;
  1613. if (startAnchor) {
  1614. startAnchor.removeEventListener('focus', this.startAnchorListener);
  1615. if (startAnchor.parentNode) {
  1616. startAnchor.parentNode.removeChild(startAnchor);
  1617. }
  1618. }
  1619. if (endAnchor) {
  1620. endAnchor.removeEventListener('focus', this.endAnchorListener);
  1621. if (endAnchor.parentNode) {
  1622. endAnchor.parentNode.removeChild(endAnchor);
  1623. }
  1624. }
  1625. this._startAnchor = this._endAnchor = null;
  1626. };
  1627. /**
  1628. * Inserts the anchors into the DOM. This is usually done automatically
  1629. * in the constructor, but can be deferred for cases like directives with `*ngIf`.
  1630. * @returns Whether the focus trap managed to attach successfuly. This may not be the case
  1631. * if the target element isn't currently in the DOM.
  1632. */
  1633. /**
  1634. * Inserts the anchors into the DOM. This is usually done automatically
  1635. * in the constructor, but can be deferred for cases like directives with `*ngIf`.
  1636. * @return {?} Whether the focus trap managed to attach successfuly. This may not be the case
  1637. * if the target element isn't currently in the DOM.
  1638. */
  1639. FocusTrap.prototype.attachAnchors = /**
  1640. * Inserts the anchors into the DOM. This is usually done automatically
  1641. * in the constructor, but can be deferred for cases like directives with `*ngIf`.
  1642. * @return {?} Whether the focus trap managed to attach successfuly. This may not be the case
  1643. * if the target element isn't currently in the DOM.
  1644. */
  1645. function () {
  1646. var _this = this;
  1647. // If we're not on the browser, there can be no focus to trap.
  1648. if (this._hasAttached) {
  1649. return true;
  1650. }
  1651. this._ngZone.runOutsideAngular((/**
  1652. * @return {?}
  1653. */
  1654. function () {
  1655. if (!_this._startAnchor) {
  1656. _this._startAnchor = _this._createAnchor();
  1657. (/** @type {?} */ (_this._startAnchor)).addEventListener('focus', _this.startAnchorListener);
  1658. }
  1659. if (!_this._endAnchor) {
  1660. _this._endAnchor = _this._createAnchor();
  1661. (/** @type {?} */ (_this._endAnchor)).addEventListener('focus', _this.endAnchorListener);
  1662. }
  1663. }));
  1664. if (this._element.parentNode) {
  1665. this._element.parentNode.insertBefore((/** @type {?} */ (this._startAnchor)), this._element);
  1666. this._element.parentNode.insertBefore((/** @type {?} */ (this._endAnchor)), this._element.nextSibling);
  1667. this._hasAttached = true;
  1668. }
  1669. return this._hasAttached;
  1670. };
  1671. /**
  1672. * Waits for the zone to stabilize, then either focuses the first element that the
  1673. * user specified, or the first tabbable element.
  1674. * @returns Returns a promise that resolves with a boolean, depending
  1675. * on whether focus was moved successfuly.
  1676. */
  1677. /**
  1678. * Waits for the zone to stabilize, then either focuses the first element that the
  1679. * user specified, or the first tabbable element.
  1680. * @return {?} Returns a promise that resolves with a boolean, depending
  1681. * on whether focus was moved successfuly.
  1682. */
  1683. FocusTrap.prototype.focusInitialElementWhenReady = /**
  1684. * Waits for the zone to stabilize, then either focuses the first element that the
  1685. * user specified, or the first tabbable element.
  1686. * @return {?} Returns a promise that resolves with a boolean, depending
  1687. * on whether focus was moved successfuly.
  1688. */
  1689. function () {
  1690. var _this = this;
  1691. return new Promise((/**
  1692. * @param {?} resolve
  1693. * @return {?}
  1694. */
  1695. function (resolve) {
  1696. _this._executeOnStable((/**
  1697. * @return {?}
  1698. */
  1699. function () { return resolve(_this.focusInitialElement()); }));
  1700. }));
  1701. };
  1702. /**
  1703. * Waits for the zone to stabilize, then focuses
  1704. * the first tabbable element within the focus trap region.
  1705. * @returns Returns a promise that resolves with a boolean, depending
  1706. * on whether focus was moved successfuly.
  1707. */
  1708. /**
  1709. * Waits for the zone to stabilize, then focuses
  1710. * the first tabbable element within the focus trap region.
  1711. * @return {?} Returns a promise that resolves with a boolean, depending
  1712. * on whether focus was moved successfuly.
  1713. */
  1714. FocusTrap.prototype.focusFirstTabbableElementWhenReady = /**
  1715. * Waits for the zone to stabilize, then focuses
  1716. * the first tabbable element within the focus trap region.
  1717. * @return {?} Returns a promise that resolves with a boolean, depending
  1718. * on whether focus was moved successfuly.
  1719. */
  1720. function () {
  1721. var _this = this;
  1722. return new Promise((/**
  1723. * @param {?} resolve
  1724. * @return {?}
  1725. */
  1726. function (resolve) {
  1727. _this._executeOnStable((/**
  1728. * @return {?}
  1729. */
  1730. function () { return resolve(_this.focusFirstTabbableElement()); }));
  1731. }));
  1732. };
  1733. /**
  1734. * Waits for the zone to stabilize, then focuses
  1735. * the last tabbable element within the focus trap region.
  1736. * @returns Returns a promise that resolves with a boolean, depending
  1737. * on whether focus was moved successfuly.
  1738. */
  1739. /**
  1740. * Waits for the zone to stabilize, then focuses
  1741. * the last tabbable element within the focus trap region.
  1742. * @return {?} Returns a promise that resolves with a boolean, depending
  1743. * on whether focus was moved successfuly.
  1744. */
  1745. FocusTrap.prototype.focusLastTabbableElementWhenReady = /**
  1746. * Waits for the zone to stabilize, then focuses
  1747. * the last tabbable element within the focus trap region.
  1748. * @return {?} Returns a promise that resolves with a boolean, depending
  1749. * on whether focus was moved successfuly.
  1750. */
  1751. function () {
  1752. var _this = this;
  1753. return new Promise((/**
  1754. * @param {?} resolve
  1755. * @return {?}
  1756. */
  1757. function (resolve) {
  1758. _this._executeOnStable((/**
  1759. * @return {?}
  1760. */
  1761. function () { return resolve(_this.focusLastTabbableElement()); }));
  1762. }));
  1763. };
  1764. /**
  1765. * Get the specified boundary element of the trapped region.
  1766. * @param bound The boundary to get (start or end of trapped region).
  1767. * @returns The boundary element.
  1768. */
  1769. /**
  1770. * Get the specified boundary element of the trapped region.
  1771. * @private
  1772. * @param {?} bound The boundary to get (start or end of trapped region).
  1773. * @return {?} The boundary element.
  1774. */
  1775. FocusTrap.prototype._getRegionBoundary = /**
  1776. * Get the specified boundary element of the trapped region.
  1777. * @private
  1778. * @param {?} bound The boundary to get (start or end of trapped region).
  1779. * @return {?} The boundary element.
  1780. */
  1781. function (bound) {
  1782. // Contains the deprecated version of selector, for temporary backwards comparability.
  1783. /** @type {?} */
  1784. var markers = (/** @type {?} */ (this._element.querySelectorAll("[cdk-focus-region-" + bound + "], " +
  1785. ("[cdkFocusRegion" + bound + "], ") +
  1786. ("[cdk-focus-" + bound + "]"))));
  1787. for (var i = 0; i < markers.length; i++) {
  1788. // @breaking-change 8.0.0
  1789. if (markers[i].hasAttribute("cdk-focus-" + bound)) {
  1790. console.warn("Found use of deprecated attribute 'cdk-focus-" + bound + "', " +
  1791. ("use 'cdkFocusRegion" + bound + "' instead. The deprecated ") +
  1792. "attribute will be removed in 8.0.0.", markers[i]);
  1793. }
  1794. else if (markers[i].hasAttribute("cdk-focus-region-" + bound)) {
  1795. console.warn("Found use of deprecated attribute 'cdk-focus-region-" + bound + "', " +
  1796. ("use 'cdkFocusRegion" + bound + "' instead. The deprecated attribute ") +
  1797. "will be removed in 8.0.0.", markers[i]);
  1798. }
  1799. }
  1800. if (bound == 'start') {
  1801. return markers.length ? markers[0] : this._getFirstTabbableElement(this._element);
  1802. }
  1803. return markers.length ?
  1804. markers[markers.length - 1] : this._getLastTabbableElement(this._element);
  1805. };
  1806. /**
  1807. * Focuses the element that should be focused when the focus trap is initialized.
  1808. * @returns Whether focus was moved successfuly.
  1809. */
  1810. /**
  1811. * Focuses the element that should be focused when the focus trap is initialized.
  1812. * @return {?} Whether focus was moved successfuly.
  1813. */
  1814. FocusTrap.prototype.focusInitialElement = /**
  1815. * Focuses the element that should be focused when the focus trap is initialized.
  1816. * @return {?} Whether focus was moved successfuly.
  1817. */
  1818. function () {
  1819. // Contains the deprecated version of selector, for temporary backwards comparability.
  1820. /** @type {?} */
  1821. var redirectToElement = (/** @type {?} */ (this._element.querySelector("[cdk-focus-initial], " +
  1822. "[cdkFocusInitial]")));
  1823. if (redirectToElement) {
  1824. // @breaking-change 8.0.0
  1825. if (redirectToElement.hasAttribute("cdk-focus-initial")) {
  1826. console.warn("Found use of deprecated attribute 'cdk-focus-initial', " +
  1827. "use 'cdkFocusInitial' instead. The deprecated attribute " +
  1828. "will be removed in 8.0.0", redirectToElement);
  1829. }
  1830. // Warn the consumer if the element they've pointed to
  1831. // isn't focusable, when not in production mode.
  1832. if (isDevMode() && !this._checker.isFocusable(redirectToElement)) {
  1833. console.warn("Element matching '[cdkFocusInitial]' is not focusable.", redirectToElement);
  1834. }
  1835. redirectToElement.focus();
  1836. return true;
  1837. }
  1838. return this.focusFirstTabbableElement();
  1839. };
  1840. /**
  1841. * Focuses the first tabbable element within the focus trap region.
  1842. * @returns Whether focus was moved successfuly.
  1843. */
  1844. /**
  1845. * Focuses the first tabbable element within the focus trap region.
  1846. * @return {?} Whether focus was moved successfuly.
  1847. */
  1848. FocusTrap.prototype.focusFirstTabbableElement = /**
  1849. * Focuses the first tabbable element within the focus trap region.
  1850. * @return {?} Whether focus was moved successfuly.
  1851. */
  1852. function () {
  1853. /** @type {?} */
  1854. var redirectToElement = this._getRegionBoundary('start');
  1855. if (redirectToElement) {
  1856. redirectToElement.focus();
  1857. }
  1858. return !!redirectToElement;
  1859. };
  1860. /**
  1861. * Focuses the last tabbable element within the focus trap region.
  1862. * @returns Whether focus was moved successfuly.
  1863. */
  1864. /**
  1865. * Focuses the last tabbable element within the focus trap region.
  1866. * @return {?} Whether focus was moved successfuly.
  1867. */
  1868. FocusTrap.prototype.focusLastTabbableElement = /**
  1869. * Focuses the last tabbable element within the focus trap region.
  1870. * @return {?} Whether focus was moved successfuly.
  1871. */
  1872. function () {
  1873. /** @type {?} */
  1874. var redirectToElement = this._getRegionBoundary('end');
  1875. if (redirectToElement) {
  1876. redirectToElement.focus();
  1877. }
  1878. return !!redirectToElement;
  1879. };
  1880. /**
  1881. * Checks whether the focus trap has successfuly been attached.
  1882. */
  1883. /**
  1884. * Checks whether the focus trap has successfuly been attached.
  1885. * @return {?}
  1886. */
  1887. FocusTrap.prototype.hasAttached = /**
  1888. * Checks whether the focus trap has successfuly been attached.
  1889. * @return {?}
  1890. */
  1891. function () {
  1892. return this._hasAttached;
  1893. };
  1894. /** Get the first tabbable element from a DOM subtree (inclusive). */
  1895. /**
  1896. * Get the first tabbable element from a DOM subtree (inclusive).
  1897. * @private
  1898. * @param {?} root
  1899. * @return {?}
  1900. */
  1901. FocusTrap.prototype._getFirstTabbableElement = /**
  1902. * Get the first tabbable element from a DOM subtree (inclusive).
  1903. * @private
  1904. * @param {?} root
  1905. * @return {?}
  1906. */
  1907. function (root) {
  1908. if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
  1909. return root;
  1910. }
  1911. // Iterate in DOM order. Note that IE doesn't have `children` for SVG so we fall
  1912. // back to `childNodes` which includes text nodes, comments etc.
  1913. /** @type {?} */
  1914. var children = root.children || root.childNodes;
  1915. for (var i = 0; i < children.length; i++) {
  1916. /** @type {?} */
  1917. var tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
  1918. this._getFirstTabbableElement((/** @type {?} */ (children[i]))) :
  1919. null;
  1920. if (tabbableChild) {
  1921. return tabbableChild;
  1922. }
  1923. }
  1924. return null;
  1925. };
  1926. /** Get the last tabbable element from a DOM subtree (inclusive). */
  1927. /**
  1928. * Get the last tabbable element from a DOM subtree (inclusive).
  1929. * @private
  1930. * @param {?} root
  1931. * @return {?}
  1932. */
  1933. FocusTrap.prototype._getLastTabbableElement = /**
  1934. * Get the last tabbable element from a DOM subtree (inclusive).
  1935. * @private
  1936. * @param {?} root
  1937. * @return {?}
  1938. */
  1939. function (root) {
  1940. if (this._checker.isFocusable(root) && this._checker.isTabbable(root)) {
  1941. return root;
  1942. }
  1943. // Iterate in reverse DOM order.
  1944. /** @type {?} */
  1945. var children = root.children || root.childNodes;
  1946. for (var i = children.length - 1; i >= 0; i--) {
  1947. /** @type {?} */
  1948. var tabbableChild = children[i].nodeType === this._document.ELEMENT_NODE ?
  1949. this._getLastTabbableElement((/** @type {?} */ (children[i]))) :
  1950. null;
  1951. if (tabbableChild) {
  1952. return tabbableChild;
  1953. }
  1954. }
  1955. return null;
  1956. };
  1957. /** Creates an anchor element. */
  1958. /**
  1959. * Creates an anchor element.
  1960. * @private
  1961. * @return {?}
  1962. */
  1963. FocusTrap.prototype._createAnchor = /**
  1964. * Creates an anchor element.
  1965. * @private
  1966. * @return {?}
  1967. */
  1968. function () {
  1969. /** @type {?} */
  1970. var anchor = this._document.createElement('div');
  1971. this._toggleAnchorTabIndex(this._enabled, anchor);
  1972. anchor.classList.add('cdk-visually-hidden');
  1973. anchor.classList.add('cdk-focus-trap-anchor');
  1974. anchor.setAttribute('aria-hidden', 'true');
  1975. return anchor;
  1976. };
  1977. /**
  1978. * Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.
  1979. * @param isEnabled Whether the focus trap is enabled.
  1980. * @param anchor Anchor on which to toggle the tabindex.
  1981. */
  1982. /**
  1983. * Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.
  1984. * @private
  1985. * @param {?} isEnabled Whether the focus trap is enabled.
  1986. * @param {?} anchor Anchor on which to toggle the tabindex.
  1987. * @return {?}
  1988. */
  1989. FocusTrap.prototype._toggleAnchorTabIndex = /**
  1990. * Toggles the `tabindex` of an anchor, based on the enabled state of the focus trap.
  1991. * @private
  1992. * @param {?} isEnabled Whether the focus trap is enabled.
  1993. * @param {?} anchor Anchor on which to toggle the tabindex.
  1994. * @return {?}
  1995. */
  1996. function (isEnabled, anchor) {
  1997. // Remove the tabindex completely, rather than setting it to -1, because if the
  1998. // element has a tabindex, the user might still hit it when navigating with the arrow keys.
  1999. isEnabled ? anchor.setAttribute('tabindex', '0') : anchor.removeAttribute('tabindex');
  2000. };
  2001. /** Executes a function when the zone is stable. */
  2002. /**
  2003. * Executes a function when the zone is stable.
  2004. * @private
  2005. * @param {?} fn
  2006. * @return {?}
  2007. */
  2008. FocusTrap.prototype._executeOnStable = /**
  2009. * Executes a function when the zone is stable.
  2010. * @private
  2011. * @param {?} fn
  2012. * @return {?}
  2013. */
  2014. function (fn) {
  2015. if (this._ngZone.isStable) {
  2016. fn();
  2017. }
  2018. else {
  2019. this._ngZone.onStable.asObservable().pipe(take(1)).subscribe(fn);
  2020. }
  2021. };
  2022. return FocusTrap;
  2023. }());
  2024. /**
  2025. * Factory that allows easy instantiation of focus traps.
  2026. */
  2027. var FocusTrapFactory = /** @class */ (function () {
  2028. function FocusTrapFactory(_checker, _ngZone, _document) {
  2029. this._checker = _checker;
  2030. this._ngZone = _ngZone;
  2031. this._document = _document;
  2032. }
  2033. /**
  2034. * Creates a focus-trapped region around the given element.
  2035. * @param element The element around which focus will be trapped.
  2036. * @param deferCaptureElements Defers the creation of focus-capturing elements to be done
  2037. * manually by the user.
  2038. * @returns The created focus trap instance.
  2039. */
  2040. /**
  2041. * Creates a focus-trapped region around the given element.
  2042. * @param {?} element The element around which focus will be trapped.
  2043. * @param {?=} deferCaptureElements Defers the creation of focus-capturing elements to be done
  2044. * manually by the user.
  2045. * @return {?} The created focus trap instance.
  2046. */
  2047. FocusTrapFactory.prototype.create = /**
  2048. * Creates a focus-trapped region around the given element.
  2049. * @param {?} element The element around which focus will be trapped.
  2050. * @param {?=} deferCaptureElements Defers the creation of focus-capturing elements to be done
  2051. * manually by the user.
  2052. * @return {?} The created focus trap instance.
  2053. */
  2054. function (element, deferCaptureElements) {
  2055. if (deferCaptureElements === void 0) { deferCaptureElements = false; }
  2056. return new FocusTrap(element, this._checker, this._ngZone, this._document, deferCaptureElements);
  2057. };
  2058. FocusTrapFactory.decorators = [
  2059. { type: Injectable, args: [{ providedIn: 'root' },] },
  2060. ];
  2061. /** @nocollapse */
  2062. FocusTrapFactory.ctorParameters = function () { return [
  2063. { type: InteractivityChecker },
  2064. { type: NgZone },
  2065. { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
  2066. ]; };
  2067. /** @nocollapse */ FocusTrapFactory.ngInjectableDef = ɵɵdefineInjectable({ factory: function FocusTrapFactory_Factory() { return new FocusTrapFactory(ɵɵinject(InteractivityChecker), ɵɵinject(NgZone), ɵɵinject(DOCUMENT)); }, token: FocusTrapFactory, providedIn: "root" });
  2068. return FocusTrapFactory;
  2069. }());
  2070. /**
  2071. * Directive for trapping focus within a region.
  2072. */
  2073. var CdkTrapFocus = /** @class */ (function () {
  2074. function CdkTrapFocus(_elementRef, _focusTrapFactory, _document) {
  2075. this._elementRef = _elementRef;
  2076. this._focusTrapFactory = _focusTrapFactory;
  2077. /**
  2078. * Previously focused element to restore focus to upon destroy when using autoCapture.
  2079. */
  2080. this._previouslyFocusedElement = null;
  2081. this._document = _document;
  2082. this.focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement, true);
  2083. }
  2084. Object.defineProperty(CdkTrapFocus.prototype, "enabled", {
  2085. /** Whether the focus trap is active. */
  2086. get: /**
  2087. * Whether the focus trap is active.
  2088. * @return {?}
  2089. */
  2090. function () { return this.focusTrap.enabled; },
  2091. set: /**
  2092. * @param {?} value
  2093. * @return {?}
  2094. */
  2095. function (value) { this.focusTrap.enabled = coerceBooleanProperty(value); },
  2096. enumerable: true,
  2097. configurable: true
  2098. });
  2099. Object.defineProperty(CdkTrapFocus.prototype, "autoCapture", {
  2100. /**
  2101. * Whether the directive should automatially move focus into the trapped region upon
  2102. * initialization and return focus to the previous activeElement upon destruction.
  2103. */
  2104. get: /**
  2105. * Whether the directive should automatially move focus into the trapped region upon
  2106. * initialization and return focus to the previous activeElement upon destruction.
  2107. * @return {?}
  2108. */
  2109. function () { return this._autoCapture; },
  2110. set: /**
  2111. * @param {?} value
  2112. * @return {?}
  2113. */
  2114. function (value) { this._autoCapture = coerceBooleanProperty(value); },
  2115. enumerable: true,
  2116. configurable: true
  2117. });
  2118. /**
  2119. * @return {?}
  2120. */
  2121. CdkTrapFocus.prototype.ngOnDestroy = /**
  2122. * @return {?}
  2123. */
  2124. function () {
  2125. this.focusTrap.destroy();
  2126. // If we stored a previously focused element when using autoCapture, return focus to that
  2127. // element now that the trapped region is being destroyed.
  2128. if (this._previouslyFocusedElement) {
  2129. this._previouslyFocusedElement.focus();
  2130. this._previouslyFocusedElement = null;
  2131. }
  2132. };
  2133. /**
  2134. * @return {?}
  2135. */
  2136. CdkTrapFocus.prototype.ngAfterContentInit = /**
  2137. * @return {?}
  2138. */
  2139. function () {
  2140. this.focusTrap.attachAnchors();
  2141. if (this.autoCapture) {
  2142. this._previouslyFocusedElement = (/** @type {?} */ (this._document.activeElement));
  2143. this.focusTrap.focusInitialElementWhenReady();
  2144. }
  2145. };
  2146. /**
  2147. * @return {?}
  2148. */
  2149. CdkTrapFocus.prototype.ngDoCheck = /**
  2150. * @return {?}
  2151. */
  2152. function () {
  2153. if (!this.focusTrap.hasAttached()) {
  2154. this.focusTrap.attachAnchors();
  2155. }
  2156. };
  2157. CdkTrapFocus.decorators = [
  2158. { type: Directive, args: [{
  2159. selector: '[cdkTrapFocus]',
  2160. exportAs: 'cdkTrapFocus',
  2161. },] },
  2162. ];
  2163. /** @nocollapse */
  2164. CdkTrapFocus.ctorParameters = function () { return [
  2165. { type: ElementRef },
  2166. { type: FocusTrapFactory },
  2167. { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
  2168. ]; };
  2169. CdkTrapFocus.propDecorators = {
  2170. enabled: [{ type: Input, args: ['cdkTrapFocus',] }],
  2171. autoCapture: [{ type: Input, args: ['cdkTrapFocusAutoCapture',] }]
  2172. };
  2173. return CdkTrapFocus;
  2174. }());
  2175. /**
  2176. * @fileoverview added by tsickle
  2177. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  2178. */
  2179. /** @type {?} */
  2180. var LIVE_ANNOUNCER_ELEMENT_TOKEN = new InjectionToken('liveAnnouncerElement', {
  2181. providedIn: 'root',
  2182. factory: LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY,
  2183. });
  2184. /**
  2185. * \@docs-private
  2186. * @return {?}
  2187. */
  2188. function LIVE_ANNOUNCER_ELEMENT_TOKEN_FACTORY() {
  2189. return null;
  2190. }
  2191. /**
  2192. * Injection token that can be used to configure the default options for the LiveAnnouncer.
  2193. * @type {?}
  2194. */
  2195. var LIVE_ANNOUNCER_DEFAULT_OPTIONS = new InjectionToken('LIVE_ANNOUNCER_DEFAULT_OPTIONS');
  2196. /**
  2197. * @fileoverview added by tsickle
  2198. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  2199. */
  2200. var LiveAnnouncer = /** @class */ (function () {
  2201. function LiveAnnouncer(elementToken, _ngZone, _document, _defaultOptions) {
  2202. this._ngZone = _ngZone;
  2203. this._defaultOptions = _defaultOptions;
  2204. // We inject the live element and document as `any` because the constructor signature cannot
  2205. // reference browser globals (HTMLElement, Document) on non-browser environments, since having
  2206. // a class decorator causes TypeScript to preserve the constructor signature types.
  2207. this._document = _document;
  2208. this._liveElement = elementToken || this._createLiveElement();
  2209. }
  2210. /**
  2211. * @param {?} message
  2212. * @param {...?} args
  2213. * @return {?}
  2214. */
  2215. LiveAnnouncer.prototype.announce = /**
  2216. * @param {?} message
  2217. * @param {...?} args
  2218. * @return {?}
  2219. */
  2220. function (message) {
  2221. var _this = this;
  2222. var args = [];
  2223. for (var _i = 1; _i < arguments.length; _i++) {
  2224. args[_i - 1] = arguments[_i];
  2225. }
  2226. /** @type {?} */
  2227. var defaultOptions = this._defaultOptions;
  2228. /** @type {?} */
  2229. var politeness;
  2230. /** @type {?} */
  2231. var duration;
  2232. if (args.length === 1 && typeof args[0] === 'number') {
  2233. duration = args[0];
  2234. }
  2235. else {
  2236. politeness = args[0], duration = args[1];
  2237. }
  2238. this.clear();
  2239. clearTimeout(this._previousTimeout);
  2240. if (!politeness) {
  2241. politeness =
  2242. (defaultOptions && defaultOptions.politeness) ? defaultOptions.politeness : 'polite';
  2243. }
  2244. if (duration == null && defaultOptions) {
  2245. duration = defaultOptions.duration;
  2246. }
  2247. // TODO: ensure changing the politeness works on all environments we support.
  2248. this._liveElement.setAttribute('aria-live', politeness);
  2249. // This 100ms timeout is necessary for some browser + screen-reader combinations:
  2250. // - Both JAWS and NVDA over IE11 will not announce anything without a non-zero timeout.
  2251. // - With Chrome and IE11 with NVDA or JAWS, a repeated (identical) message won't be read a
  2252. // second time without clearing and then using a non-zero delay.
  2253. // (using JAWS 17 at time of this writing).
  2254. return this._ngZone.runOutsideAngular((/**
  2255. * @return {?}
  2256. */
  2257. function () {
  2258. return new Promise((/**
  2259. * @param {?} resolve
  2260. * @return {?}
  2261. */
  2262. function (resolve) {
  2263. clearTimeout(_this._previousTimeout);
  2264. _this._previousTimeout = setTimeout((/**
  2265. * @return {?}
  2266. */
  2267. function () {
  2268. _this._liveElement.textContent = message;
  2269. resolve();
  2270. if (typeof duration === 'number') {
  2271. _this._previousTimeout = setTimeout((/**
  2272. * @return {?}
  2273. */
  2274. function () { return _this.clear(); }), duration);
  2275. }
  2276. }), 100);
  2277. }));
  2278. }));
  2279. };
  2280. /**
  2281. * Clears the current text from the announcer element. Can be used to prevent
  2282. * screen readers from reading the text out again while the user is going
  2283. * through the page landmarks.
  2284. */
  2285. /**
  2286. * Clears the current text from the announcer element. Can be used to prevent
  2287. * screen readers from reading the text out again while the user is going
  2288. * through the page landmarks.
  2289. * @return {?}
  2290. */
  2291. LiveAnnouncer.prototype.clear = /**
  2292. * Clears the current text from the announcer element. Can be used to prevent
  2293. * screen readers from reading the text out again while the user is going
  2294. * through the page landmarks.
  2295. * @return {?}
  2296. */
  2297. function () {
  2298. if (this._liveElement) {
  2299. this._liveElement.textContent = '';
  2300. }
  2301. };
  2302. /**
  2303. * @return {?}
  2304. */
  2305. LiveAnnouncer.prototype.ngOnDestroy = /**
  2306. * @return {?}
  2307. */
  2308. function () {
  2309. clearTimeout(this._previousTimeout);
  2310. if (this._liveElement && this._liveElement.parentNode) {
  2311. this._liveElement.parentNode.removeChild(this._liveElement);
  2312. this._liveElement = (/** @type {?} */ (null));
  2313. }
  2314. };
  2315. /**
  2316. * @private
  2317. * @return {?}
  2318. */
  2319. LiveAnnouncer.prototype._createLiveElement = /**
  2320. * @private
  2321. * @return {?}
  2322. */
  2323. function () {
  2324. /** @type {?} */
  2325. var elementClass = 'cdk-live-announcer-element';
  2326. /** @type {?} */
  2327. var previousElements = this._document.getElementsByClassName(elementClass);
  2328. /** @type {?} */
  2329. var liveEl = this._document.createElement('div');
  2330. // Remove any old containers. This can happen when coming in from a server-side-rendered page.
  2331. for (var i = 0; i < previousElements.length; i++) {
  2332. (/** @type {?} */ (previousElements[i].parentNode)).removeChild(previousElements[i]);
  2333. }
  2334. liveEl.classList.add(elementClass);
  2335. liveEl.classList.add('cdk-visually-hidden');
  2336. liveEl.setAttribute('aria-atomic', 'true');
  2337. liveEl.setAttribute('aria-live', 'polite');
  2338. this._document.body.appendChild(liveEl);
  2339. return liveEl;
  2340. };
  2341. LiveAnnouncer.decorators = [
  2342. { type: Injectable, args: [{ providedIn: 'root' },] },
  2343. ];
  2344. /** @nocollapse */
  2345. LiveAnnouncer.ctorParameters = function () { return [
  2346. { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [LIVE_ANNOUNCER_ELEMENT_TOKEN,] }] },
  2347. { type: NgZone },
  2348. { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] },
  2349. { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [LIVE_ANNOUNCER_DEFAULT_OPTIONS,] }] }
  2350. ]; };
  2351. /** @nocollapse */ LiveAnnouncer.ngInjectableDef = ɵɵdefineInjectable({ factory: function LiveAnnouncer_Factory() { return new LiveAnnouncer(ɵɵinject(LIVE_ANNOUNCER_ELEMENT_TOKEN, 8), ɵɵinject(NgZone), ɵɵinject(DOCUMENT), ɵɵinject(LIVE_ANNOUNCER_DEFAULT_OPTIONS, 8)); }, token: LiveAnnouncer, providedIn: "root" });
  2352. return LiveAnnouncer;
  2353. }());
  2354. /**
  2355. * A directive that works similarly to aria-live, but uses the LiveAnnouncer to ensure compatibility
  2356. * with a wider range of browsers and screen readers.
  2357. */
  2358. var CdkAriaLive = /** @class */ (function () {
  2359. function CdkAriaLive(_elementRef, _liveAnnouncer, _contentObserver, _ngZone) {
  2360. this._elementRef = _elementRef;
  2361. this._liveAnnouncer = _liveAnnouncer;
  2362. this._contentObserver = _contentObserver;
  2363. this._ngZone = _ngZone;
  2364. this._politeness = 'off';
  2365. }
  2366. Object.defineProperty(CdkAriaLive.prototype, "politeness", {
  2367. /** The aria-live politeness level to use when announcing messages. */
  2368. get: /**
  2369. * The aria-live politeness level to use when announcing messages.
  2370. * @return {?}
  2371. */
  2372. function () { return this._politeness; },
  2373. set: /**
  2374. * @param {?} value
  2375. * @return {?}
  2376. */
  2377. function (value) {
  2378. var _this = this;
  2379. this._politeness = value === 'polite' || value === 'assertive' ? value : 'off';
  2380. if (this._politeness === 'off') {
  2381. if (this._subscription) {
  2382. this._subscription.unsubscribe();
  2383. this._subscription = null;
  2384. }
  2385. }
  2386. else if (!this._subscription) {
  2387. this._subscription = this._ngZone.runOutsideAngular((/**
  2388. * @return {?}
  2389. */
  2390. function () {
  2391. return _this._contentObserver
  2392. .observe(_this._elementRef)
  2393. .subscribe((/**
  2394. * @return {?}
  2395. */
  2396. function () {
  2397. // Note that we use textContent here, rather than innerText, in order to avoid a reflow.
  2398. /** @type {?} */
  2399. var elementText = _this._elementRef.nativeElement.textContent;
  2400. // The `MutationObserver` fires also for attribute
  2401. // changes which we don't want to announce.
  2402. if (elementText !== _this._previousAnnouncedText) {
  2403. _this._liveAnnouncer.announce(elementText, _this._politeness);
  2404. _this._previousAnnouncedText = elementText;
  2405. }
  2406. }));
  2407. }));
  2408. }
  2409. },
  2410. enumerable: true,
  2411. configurable: true
  2412. });
  2413. /**
  2414. * @return {?}
  2415. */
  2416. CdkAriaLive.prototype.ngOnDestroy = /**
  2417. * @return {?}
  2418. */
  2419. function () {
  2420. if (this._subscription) {
  2421. this._subscription.unsubscribe();
  2422. }
  2423. };
  2424. CdkAriaLive.decorators = [
  2425. { type: Directive, args: [{
  2426. selector: '[cdkAriaLive]',
  2427. exportAs: 'cdkAriaLive',
  2428. },] },
  2429. ];
  2430. /** @nocollapse */
  2431. CdkAriaLive.ctorParameters = function () { return [
  2432. { type: ElementRef },
  2433. { type: LiveAnnouncer },
  2434. { type: ContentObserver },
  2435. { type: NgZone }
  2436. ]; };
  2437. CdkAriaLive.propDecorators = {
  2438. politeness: [{ type: Input, args: ['cdkAriaLive',] }]
  2439. };
  2440. return CdkAriaLive;
  2441. }());
  2442. /**
  2443. * \@docs-private \@deprecated \@breaking-change 8.0.0
  2444. * @param {?} parentAnnouncer
  2445. * @param {?} liveElement
  2446. * @param {?} _document
  2447. * @param {?} ngZone
  2448. * @return {?}
  2449. */
  2450. function LIVE_ANNOUNCER_PROVIDER_FACTORY(parentAnnouncer, liveElement, _document, ngZone) {
  2451. return parentAnnouncer || new LiveAnnouncer(liveElement, ngZone, _document);
  2452. }
  2453. /**
  2454. * \@docs-private \@deprecated \@breaking-change 8.0.0
  2455. * @type {?}
  2456. */
  2457. var LIVE_ANNOUNCER_PROVIDER = {
  2458. // If there is already a LiveAnnouncer available, use that. Otherwise, provide a new one.
  2459. provide: LiveAnnouncer,
  2460. deps: [
  2461. [new Optional(), new SkipSelf(), LiveAnnouncer],
  2462. [new Optional(), new Inject(LIVE_ANNOUNCER_ELEMENT_TOKEN)],
  2463. DOCUMENT,
  2464. NgZone,
  2465. ],
  2466. useFactory: LIVE_ANNOUNCER_PROVIDER_FACTORY
  2467. };
  2468. /**
  2469. * @fileoverview added by tsickle
  2470. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  2471. */
  2472. // This is the value used by AngularJS Material. Through trial and error (on iPhone 6S) they found
  2473. // that a value of around 650ms seems appropriate.
  2474. /** @type {?} */
  2475. var TOUCH_BUFFER_MS = 650;
  2476. /**
  2477. * Event listener options that enable capturing and also
  2478. * mark the listener as passive if the browser supports it.
  2479. * @type {?}
  2480. */
  2481. var captureEventListenerOptions = normalizePassiveListenerOptions({
  2482. passive: true,
  2483. capture: true
  2484. });
  2485. /**
  2486. * Monitors mouse and keyboard events to determine the cause of focus events.
  2487. */
  2488. var FocusMonitor = /** @class */ (function () {
  2489. function FocusMonitor(_ngZone, _platform) {
  2490. var _this = this;
  2491. this._ngZone = _ngZone;
  2492. this._platform = _platform;
  2493. /**
  2494. * The focus origin that the next focus event is a result of.
  2495. */
  2496. this._origin = null;
  2497. /**
  2498. * Whether the window has just been focused.
  2499. */
  2500. this._windowFocused = false;
  2501. /**
  2502. * Map of elements being monitored to their info.
  2503. */
  2504. this._elementInfo = new Map();
  2505. /**
  2506. * The number of elements currently being monitored.
  2507. */
  2508. this._monitoredElementCount = 0;
  2509. /**
  2510. * Event listener for `keydown` events on the document.
  2511. * Needs to be an arrow function in order to preserve the context when it gets bound.
  2512. */
  2513. this._documentKeydownListener = (/**
  2514. * @return {?}
  2515. */
  2516. function () {
  2517. // On keydown record the origin and clear any touch event that may be in progress.
  2518. _this._lastTouchTarget = null;
  2519. _this._setOriginForCurrentEventQueue('keyboard');
  2520. });
  2521. /**
  2522. * Event listener for `mousedown` events on the document.
  2523. * Needs to be an arrow function in order to preserve the context when it gets bound.
  2524. */
  2525. this._documentMousedownListener = (/**
  2526. * @return {?}
  2527. */
  2528. function () {
  2529. // On mousedown record the origin only if there is not touch
  2530. // target, since a mousedown can happen as a result of a touch event.
  2531. if (!_this._lastTouchTarget) {
  2532. _this._setOriginForCurrentEventQueue('mouse');
  2533. }
  2534. });
  2535. /**
  2536. * Event listener for `touchstart` events on the document.
  2537. * Needs to be an arrow function in order to preserve the context when it gets bound.
  2538. */
  2539. this._documentTouchstartListener = (/**
  2540. * @param {?} event
  2541. * @return {?}
  2542. */
  2543. function (event) {
  2544. // When the touchstart event fires the focus event is not yet in the event queue. This means
  2545. // we can't rely on the trick used above (setting timeout of 1ms). Instead we wait 650ms to
  2546. // see if a focus happens.
  2547. if (_this._touchTimeoutId != null) {
  2548. clearTimeout(_this._touchTimeoutId);
  2549. }
  2550. // Since this listener is bound on the `document` level, any events coming from the shadow DOM
  2551. // will have their `target` set to the shadow root. If available, use `composedPath` to
  2552. // figure out the event target.
  2553. _this._lastTouchTarget = event.composedPath ? event.composedPath()[0] : event.target;
  2554. _this._touchTimeoutId = setTimeout((/**
  2555. * @return {?}
  2556. */
  2557. function () { return _this._lastTouchTarget = null; }), TOUCH_BUFFER_MS);
  2558. });
  2559. /**
  2560. * Event listener for `focus` events on the window.
  2561. * Needs to be an arrow function in order to preserve the context when it gets bound.
  2562. */
  2563. this._windowFocusListener = (/**
  2564. * @return {?}
  2565. */
  2566. function () {
  2567. // Make a note of when the window regains focus, so we can
  2568. // restore the origin info for the focused element.
  2569. _this._windowFocused = true;
  2570. _this._windowFocusTimeoutId = setTimeout((/**
  2571. * @return {?}
  2572. */
  2573. function () { return _this._windowFocused = false; }));
  2574. });
  2575. }
  2576. /**
  2577. * @param {?} element
  2578. * @param {?=} checkChildren
  2579. * @return {?}
  2580. */
  2581. FocusMonitor.prototype.monitor = /**
  2582. * @param {?} element
  2583. * @param {?=} checkChildren
  2584. * @return {?}
  2585. */
  2586. function (element, checkChildren) {
  2587. var _this = this;
  2588. if (checkChildren === void 0) { checkChildren = false; }
  2589. // Do nothing if we're not on the browser platform.
  2590. if (!this._platform.isBrowser) {
  2591. return of(null);
  2592. }
  2593. /** @type {?} */
  2594. var nativeElement = coerceElement(element);
  2595. // Check if we're already monitoring this element.
  2596. if (this._elementInfo.has(nativeElement)) {
  2597. /** @type {?} */
  2598. var cachedInfo = this._elementInfo.get(nativeElement);
  2599. (/** @type {?} */ (cachedInfo)).checkChildren = checkChildren;
  2600. return (/** @type {?} */ (cachedInfo)).subject.asObservable();
  2601. }
  2602. // Create monitored element info.
  2603. /** @type {?} */
  2604. var info = {
  2605. unlisten: (/**
  2606. * @return {?}
  2607. */
  2608. function () { }),
  2609. checkChildren: checkChildren,
  2610. subject: new Subject()
  2611. };
  2612. this._elementInfo.set(nativeElement, info);
  2613. this._incrementMonitoredElementCount();
  2614. // Start listening. We need to listen in capture phase since focus events don't bubble.
  2615. /** @type {?} */
  2616. var focusListener = (/**
  2617. * @param {?} event
  2618. * @return {?}
  2619. */
  2620. function (event) { return _this._onFocus(event, nativeElement); });
  2621. /** @type {?} */
  2622. var blurListener = (/**
  2623. * @param {?} event
  2624. * @return {?}
  2625. */
  2626. function (event) { return _this._onBlur(event, nativeElement); });
  2627. this._ngZone.runOutsideAngular((/**
  2628. * @return {?}
  2629. */
  2630. function () {
  2631. nativeElement.addEventListener('focus', focusListener, true);
  2632. nativeElement.addEventListener('blur', blurListener, true);
  2633. }));
  2634. // Create an unlisten function for later.
  2635. info.unlisten = (/**
  2636. * @return {?}
  2637. */
  2638. function () {
  2639. nativeElement.removeEventListener('focus', focusListener, true);
  2640. nativeElement.removeEventListener('blur', blurListener, true);
  2641. });
  2642. return info.subject.asObservable();
  2643. };
  2644. /**
  2645. * @param {?} element
  2646. * @return {?}
  2647. */
  2648. FocusMonitor.prototype.stopMonitoring = /**
  2649. * @param {?} element
  2650. * @return {?}
  2651. */
  2652. function (element) {
  2653. /** @type {?} */
  2654. var nativeElement = coerceElement(element);
  2655. /** @type {?} */
  2656. var elementInfo = this._elementInfo.get(nativeElement);
  2657. if (elementInfo) {
  2658. elementInfo.unlisten();
  2659. elementInfo.subject.complete();
  2660. this._setClasses(nativeElement);
  2661. this._elementInfo.delete(nativeElement);
  2662. this._decrementMonitoredElementCount();
  2663. }
  2664. };
  2665. /**
  2666. * @param {?} element
  2667. * @param {?} origin
  2668. * @param {?=} options
  2669. * @return {?}
  2670. */
  2671. FocusMonitor.prototype.focusVia = /**
  2672. * @param {?} element
  2673. * @param {?} origin
  2674. * @param {?=} options
  2675. * @return {?}
  2676. */
  2677. function (element, origin, options) {
  2678. /** @type {?} */
  2679. var nativeElement = coerceElement(element);
  2680. this._setOriginForCurrentEventQueue(origin);
  2681. // `focus` isn't available on the server
  2682. if (typeof nativeElement.focus === 'function') {
  2683. // Cast the element to `any`, because the TS typings don't have the `options` parameter yet.
  2684. ((/** @type {?} */ (nativeElement))).focus(options);
  2685. }
  2686. };
  2687. /**
  2688. * @return {?}
  2689. */
  2690. FocusMonitor.prototype.ngOnDestroy = /**
  2691. * @return {?}
  2692. */
  2693. function () {
  2694. var _this = this;
  2695. this._elementInfo.forEach((/**
  2696. * @param {?} _info
  2697. * @param {?} element
  2698. * @return {?}
  2699. */
  2700. function (_info, element) { return _this.stopMonitoring(element); }));
  2701. };
  2702. /**
  2703. * @private
  2704. * @param {?} element
  2705. * @param {?} className
  2706. * @param {?} shouldSet
  2707. * @return {?}
  2708. */
  2709. FocusMonitor.prototype._toggleClass = /**
  2710. * @private
  2711. * @param {?} element
  2712. * @param {?} className
  2713. * @param {?} shouldSet
  2714. * @return {?}
  2715. */
  2716. function (element, className, shouldSet) {
  2717. if (shouldSet) {
  2718. element.classList.add(className);
  2719. }
  2720. else {
  2721. element.classList.remove(className);
  2722. }
  2723. };
  2724. /**
  2725. * Sets the focus classes on the element based on the given focus origin.
  2726. * @param element The element to update the classes on.
  2727. * @param origin The focus origin.
  2728. */
  2729. /**
  2730. * Sets the focus classes on the element based on the given focus origin.
  2731. * @private
  2732. * @param {?} element The element to update the classes on.
  2733. * @param {?=} origin The focus origin.
  2734. * @return {?}
  2735. */
  2736. FocusMonitor.prototype._setClasses = /**
  2737. * Sets the focus classes on the element based on the given focus origin.
  2738. * @private
  2739. * @param {?} element The element to update the classes on.
  2740. * @param {?=} origin The focus origin.
  2741. * @return {?}
  2742. */
  2743. function (element, origin) {
  2744. /** @type {?} */
  2745. var elementInfo = this._elementInfo.get(element);
  2746. if (elementInfo) {
  2747. this._toggleClass(element, 'cdk-focused', !!origin);
  2748. this._toggleClass(element, 'cdk-touch-focused', origin === 'touch');
  2749. this._toggleClass(element, 'cdk-keyboard-focused', origin === 'keyboard');
  2750. this._toggleClass(element, 'cdk-mouse-focused', origin === 'mouse');
  2751. this._toggleClass(element, 'cdk-program-focused', origin === 'program');
  2752. }
  2753. };
  2754. /**
  2755. * Sets the origin and schedules an async function to clear it at the end of the event queue.
  2756. * @param origin The origin to set.
  2757. */
  2758. /**
  2759. * Sets the origin and schedules an async function to clear it at the end of the event queue.
  2760. * @private
  2761. * @param {?} origin The origin to set.
  2762. * @return {?}
  2763. */
  2764. FocusMonitor.prototype._setOriginForCurrentEventQueue = /**
  2765. * Sets the origin and schedules an async function to clear it at the end of the event queue.
  2766. * @private
  2767. * @param {?} origin The origin to set.
  2768. * @return {?}
  2769. */
  2770. function (origin) {
  2771. var _this = this;
  2772. this._ngZone.runOutsideAngular((/**
  2773. * @return {?}
  2774. */
  2775. function () {
  2776. _this._origin = origin;
  2777. // Sometimes the focus origin won't be valid in Firefox because Firefox seems to focus *one*
  2778. // tick after the interaction event fired. To ensure the focus origin is always correct,
  2779. // the focus origin will be determined at the beginning of the next tick.
  2780. _this._originTimeoutId = setTimeout((/**
  2781. * @return {?}
  2782. */
  2783. function () { return _this._origin = null; }), 1);
  2784. }));
  2785. };
  2786. /**
  2787. * Checks whether the given focus event was caused by a touchstart event.
  2788. * @param event The focus event to check.
  2789. * @returns Whether the event was caused by a touch.
  2790. */
  2791. /**
  2792. * Checks whether the given focus event was caused by a touchstart event.
  2793. * @private
  2794. * @param {?} event The focus event to check.
  2795. * @return {?} Whether the event was caused by a touch.
  2796. */
  2797. FocusMonitor.prototype._wasCausedByTouch = /**
  2798. * Checks whether the given focus event was caused by a touchstart event.
  2799. * @private
  2800. * @param {?} event The focus event to check.
  2801. * @return {?} Whether the event was caused by a touch.
  2802. */
  2803. function (event) {
  2804. // Note(mmalerba): This implementation is not quite perfect, there is a small edge case.
  2805. // Consider the following dom structure:
  2806. //
  2807. // <div #parent tabindex="0" cdkFocusClasses>
  2808. // <div #child (click)="#parent.focus()"></div>
  2809. // </div>
  2810. //
  2811. // If the user touches the #child element and the #parent is programmatically focused as a
  2812. // result, this code will still consider it to have been caused by the touch event and will
  2813. // apply the cdk-touch-focused class rather than the cdk-program-focused class. This is a
  2814. // relatively small edge-case that can be worked around by using
  2815. // focusVia(parentEl, 'program') to focus the parent element.
  2816. //
  2817. // If we decide that we absolutely must handle this case correctly, we can do so by listening
  2818. // for the first focus event after the touchstart, and then the first blur event after that
  2819. // focus event. When that blur event fires we know that whatever follows is not a result of the
  2820. // touchstart.
  2821. /** @type {?} */
  2822. var focusTarget = event.target;
  2823. return this._lastTouchTarget instanceof Node && focusTarget instanceof Node &&
  2824. (focusTarget === this._lastTouchTarget || focusTarget.contains(this._lastTouchTarget));
  2825. };
  2826. /**
  2827. * Handles focus events on a registered element.
  2828. * @param event The focus event.
  2829. * @param element The monitored element.
  2830. */
  2831. /**
  2832. * Handles focus events on a registered element.
  2833. * @private
  2834. * @param {?} event The focus event.
  2835. * @param {?} element The monitored element.
  2836. * @return {?}
  2837. */
  2838. FocusMonitor.prototype._onFocus = /**
  2839. * Handles focus events on a registered element.
  2840. * @private
  2841. * @param {?} event The focus event.
  2842. * @param {?} element The monitored element.
  2843. * @return {?}
  2844. */
  2845. function (event, element) {
  2846. // NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent
  2847. // focus event affecting the monitored element. If we want to use the origin of the first event
  2848. // instead we should check for the cdk-focused class here and return if the element already has
  2849. // it. (This only matters for elements that have includesChildren = true).
  2850. // NOTE(mmalerba): We currently set the classes based on the focus origin of the most recent
  2851. // focus event affecting the monitored element. If we want to use the origin of the first event
  2852. // instead we should check for the cdk-focused class here and return if the element already has
  2853. // it. (This only matters for elements that have includesChildren = true).
  2854. // If we are not counting child-element-focus as focused, make sure that the event target is the
  2855. // monitored element itself.
  2856. /** @type {?} */
  2857. var elementInfo = this._elementInfo.get(element);
  2858. if (!elementInfo || (!elementInfo.checkChildren && element !== event.target)) {
  2859. return;
  2860. }
  2861. // If we couldn't detect a cause for the focus event, it's due to one of three reasons:
  2862. // 1) The window has just regained focus, in which case we want to restore the focused state of
  2863. // the element from before the window blurred.
  2864. // 2) It was caused by a touch event, in which case we mark the origin as 'touch'.
  2865. // 3) The element was programmatically focused, in which case we should mark the origin as
  2866. // 'program'.
  2867. /** @type {?} */
  2868. var origin = this._origin;
  2869. if (!origin) {
  2870. if (this._windowFocused && this._lastFocusOrigin) {
  2871. origin = this._lastFocusOrigin;
  2872. }
  2873. else if (this._wasCausedByTouch(event)) {
  2874. origin = 'touch';
  2875. }
  2876. else {
  2877. origin = 'program';
  2878. }
  2879. }
  2880. this._setClasses(element, origin);
  2881. this._emitOrigin(elementInfo.subject, origin);
  2882. this._lastFocusOrigin = origin;
  2883. };
  2884. /**
  2885. * Handles blur events on a registered element.
  2886. * @param event The blur event.
  2887. * @param element The monitored element.
  2888. */
  2889. /**
  2890. * Handles blur events on a registered element.
  2891. * @param {?} event The blur event.
  2892. * @param {?} element The monitored element.
  2893. * @return {?}
  2894. */
  2895. FocusMonitor.prototype._onBlur = /**
  2896. * Handles blur events on a registered element.
  2897. * @param {?} event The blur event.
  2898. * @param {?} element The monitored element.
  2899. * @return {?}
  2900. */
  2901. function (event, element) {
  2902. // If we are counting child-element-focus as focused, make sure that we aren't just blurring in
  2903. // order to focus another child of the monitored element.
  2904. /** @type {?} */
  2905. var elementInfo = this._elementInfo.get(element);
  2906. if (!elementInfo || (elementInfo.checkChildren && event.relatedTarget instanceof Node &&
  2907. element.contains(event.relatedTarget))) {
  2908. return;
  2909. }
  2910. this._setClasses(element);
  2911. this._emitOrigin(elementInfo.subject, null);
  2912. };
  2913. /**
  2914. * @private
  2915. * @param {?} subject
  2916. * @param {?} origin
  2917. * @return {?}
  2918. */
  2919. FocusMonitor.prototype._emitOrigin = /**
  2920. * @private
  2921. * @param {?} subject
  2922. * @param {?} origin
  2923. * @return {?}
  2924. */
  2925. function (subject, origin) {
  2926. this._ngZone.run((/**
  2927. * @return {?}
  2928. */
  2929. function () { return subject.next(origin); }));
  2930. };
  2931. /**
  2932. * @private
  2933. * @return {?}
  2934. */
  2935. FocusMonitor.prototype._incrementMonitoredElementCount = /**
  2936. * @private
  2937. * @return {?}
  2938. */
  2939. function () {
  2940. var _this = this;
  2941. // Register global listeners when first element is monitored.
  2942. if (++this._monitoredElementCount == 1 && this._platform.isBrowser) {
  2943. // Note: we listen to events in the capture phase so we
  2944. // can detect them even if the user stops propagation.
  2945. this._ngZone.runOutsideAngular((/**
  2946. * @return {?}
  2947. */
  2948. function () {
  2949. document.addEventListener('keydown', _this._documentKeydownListener, captureEventListenerOptions);
  2950. document.addEventListener('mousedown', _this._documentMousedownListener, captureEventListenerOptions);
  2951. document.addEventListener('touchstart', _this._documentTouchstartListener, captureEventListenerOptions);
  2952. window.addEventListener('focus', _this._windowFocusListener);
  2953. }));
  2954. }
  2955. };
  2956. /**
  2957. * @private
  2958. * @return {?}
  2959. */
  2960. FocusMonitor.prototype._decrementMonitoredElementCount = /**
  2961. * @private
  2962. * @return {?}
  2963. */
  2964. function () {
  2965. // Unregister global listeners when last element is unmonitored.
  2966. if (!--this._monitoredElementCount) {
  2967. document.removeEventListener('keydown', this._documentKeydownListener, captureEventListenerOptions);
  2968. document.removeEventListener('mousedown', this._documentMousedownListener, captureEventListenerOptions);
  2969. document.removeEventListener('touchstart', this._documentTouchstartListener, captureEventListenerOptions);
  2970. window.removeEventListener('focus', this._windowFocusListener);
  2971. // Clear timeouts for all potentially pending timeouts to prevent the leaks.
  2972. clearTimeout(this._windowFocusTimeoutId);
  2973. clearTimeout(this._touchTimeoutId);
  2974. clearTimeout(this._originTimeoutId);
  2975. }
  2976. };
  2977. FocusMonitor.decorators = [
  2978. { type: Injectable, args: [{ providedIn: 'root' },] },
  2979. ];
  2980. /** @nocollapse */
  2981. FocusMonitor.ctorParameters = function () { return [
  2982. { type: NgZone },
  2983. { type: Platform }
  2984. ]; };
  2985. /** @nocollapse */ FocusMonitor.ngInjectableDef = ɵɵdefineInjectable({ factory: function FocusMonitor_Factory() { return new FocusMonitor(ɵɵinject(NgZone), ɵɵinject(Platform)); }, token: FocusMonitor, providedIn: "root" });
  2986. return FocusMonitor;
  2987. }());
  2988. /**
  2989. * Directive that determines how a particular element was focused (via keyboard, mouse, touch, or
  2990. * programmatically) and adds corresponding classes to the element.
  2991. *
  2992. * There are two variants of this directive:
  2993. * 1) cdkMonitorElementFocus: does not consider an element to be focused if one of its children is
  2994. * focused.
  2995. * 2) cdkMonitorSubtreeFocus: considers an element focused if it or any of its children are focused.
  2996. */
  2997. var CdkMonitorFocus = /** @class */ (function () {
  2998. function CdkMonitorFocus(_elementRef, _focusMonitor) {
  2999. var _this = this;
  3000. this._elementRef = _elementRef;
  3001. this._focusMonitor = _focusMonitor;
  3002. this.cdkFocusChange = new EventEmitter();
  3003. this._monitorSubscription = this._focusMonitor.monitor(this._elementRef, this._elementRef.nativeElement.hasAttribute('cdkMonitorSubtreeFocus'))
  3004. .subscribe((/**
  3005. * @param {?} origin
  3006. * @return {?}
  3007. */
  3008. function (origin) { return _this.cdkFocusChange.emit(origin); }));
  3009. }
  3010. /**
  3011. * @return {?}
  3012. */
  3013. CdkMonitorFocus.prototype.ngOnDestroy = /**
  3014. * @return {?}
  3015. */
  3016. function () {
  3017. this._focusMonitor.stopMonitoring(this._elementRef);
  3018. this._monitorSubscription.unsubscribe();
  3019. };
  3020. CdkMonitorFocus.decorators = [
  3021. { type: Directive, args: [{
  3022. selector: '[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]',
  3023. },] },
  3024. ];
  3025. /** @nocollapse */
  3026. CdkMonitorFocus.ctorParameters = function () { return [
  3027. { type: ElementRef },
  3028. { type: FocusMonitor }
  3029. ]; };
  3030. CdkMonitorFocus.propDecorators = {
  3031. cdkFocusChange: [{ type: Output }]
  3032. };
  3033. return CdkMonitorFocus;
  3034. }());
  3035. /**
  3036. * \@docs-private \@deprecated \@breaking-change 8.0.0
  3037. * @param {?} parentDispatcher
  3038. * @param {?} ngZone
  3039. * @param {?} platform
  3040. * @return {?}
  3041. */
  3042. function FOCUS_MONITOR_PROVIDER_FACTORY(parentDispatcher, ngZone, platform) {
  3043. return parentDispatcher || new FocusMonitor(ngZone, platform);
  3044. }
  3045. /**
  3046. * \@docs-private \@deprecated \@breaking-change 8.0.0
  3047. * @type {?}
  3048. */
  3049. var FOCUS_MONITOR_PROVIDER = {
  3050. // If there is already a FocusMonitor available, use that. Otherwise, provide a new one.
  3051. provide: FocusMonitor,
  3052. deps: [[new Optional(), new SkipSelf(), FocusMonitor], NgZone, Platform],
  3053. useFactory: FOCUS_MONITOR_PROVIDER_FACTORY
  3054. };
  3055. /**
  3056. * @fileoverview added by tsickle
  3057. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  3058. */
  3059. /**
  3060. * Screenreaders will often fire fake mousedown events when a focusable element
  3061. * is activated using the keyboard. We can typically distinguish between these faked
  3062. * mousedown events and real mousedown events using the "buttons" property. While
  3063. * real mousedowns will indicate the mouse button that was pressed (e.g. "1" for
  3064. * the left mouse button), faked mousedowns will usually set the property value to 0.
  3065. * @param {?} event
  3066. * @return {?}
  3067. */
  3068. function isFakeMousedownFromScreenReader(event) {
  3069. return event.buttons === 0;
  3070. }
  3071. /**
  3072. * @fileoverview added by tsickle
  3073. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  3074. */
  3075. var A11yModule = /** @class */ (function () {
  3076. function A11yModule() {
  3077. }
  3078. A11yModule.decorators = [
  3079. { type: NgModule, args: [{
  3080. imports: [CommonModule, PlatformModule, ObserversModule],
  3081. declarations: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],
  3082. exports: [CdkAriaLive, CdkTrapFocus, CdkMonitorFocus],
  3083. },] },
  3084. ];
  3085. return A11yModule;
  3086. }());
  3087. /**
  3088. * @fileoverview added by tsickle
  3089. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  3090. */
  3091. /**
  3092. * @fileoverview added by tsickle
  3093. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  3094. */
  3095. 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, LIVE_ANNOUNCER_DEFAULT_OPTIONS, FOCUS_MONITOR_PROVIDER_FACTORY, TOUCH_BUFFER_MS, FocusMonitor, CdkMonitorFocus, FOCUS_MONITOR_PROVIDER, isFakeMousedownFromScreenReader, A11yModule };
  3096. //# sourceMappingURL=a11y.es5.js.map