Drupal investigation

js_o5DbfDWhHnEI-uMTBwCAEYoINNOLvyG60TIDmiJGAzI.js 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. /**
  2. * @file
  3. * Parse inline JSON and initialize the drupalSettings global object.
  4. */
  5. (function () {
  6. 'use strict';
  7. // Use direct child elements to harden against XSS exploits when CSP is on.
  8. var settingsElement = document.querySelector('head > script[type="application/json"][data-drupal-selector="drupal-settings-json"], body > script[type="application/json"][data-drupal-selector="drupal-settings-json"]');
  9. /**
  10. * Variable generated by Drupal with all the configuration created from PHP.
  11. *
  12. * @global
  13. *
  14. * @type {object}
  15. */
  16. window.drupalSettings = {};
  17. if (settingsElement !== null) {
  18. window.drupalSettings = JSON.parse(settingsElement.textContent);
  19. }
  20. })();
  21. ;
  22. /**
  23. * @file
  24. * Defines the Drupal JavaScript API.
  25. */
  26. /**
  27. * A jQuery object, typically the return value from a `$(selector)` call.
  28. *
  29. * Holds an HTMLElement or a collection of HTMLElements.
  30. *
  31. * @typedef {object} jQuery
  32. *
  33. * @prop {number} length=0
  34. * Number of elements contained in the jQuery object.
  35. */
  36. /**
  37. * Variable generated by Drupal that holds all translated strings from PHP.
  38. *
  39. * Content of this variable is automatically created by Drupal when using the
  40. * Interface Translation module. It holds the translation of strings used on
  41. * the page.
  42. *
  43. * This variable is used to pass data from the backend to the frontend. Data
  44. * contained in `drupalSettings` is used during behavior initialization.
  45. *
  46. * @global
  47. *
  48. * @var {object} drupalTranslations
  49. */
  50. /**
  51. * Global Drupal object.
  52. *
  53. * All Drupal JavaScript APIs are contained in this namespace.
  54. *
  55. * @global
  56. *
  57. * @namespace
  58. */
  59. window.Drupal = {behaviors: {}, locale: {}};
  60. // JavaScript should be made compatible with libraries other than jQuery by
  61. // wrapping it in an anonymous closure.
  62. (function (Drupal, drupalSettings, drupalTranslations) {
  63. 'use strict';
  64. /**
  65. * Helper to rethrow errors asynchronously.
  66. *
  67. * This way Errors bubbles up outside of the original callstack, making it
  68. * easier to debug errors in the browser.
  69. *
  70. * @param {Error|string} error
  71. * The error to be thrown.
  72. */
  73. Drupal.throwError = function (error) {
  74. setTimeout(function () { throw error; }, 0);
  75. };
  76. /**
  77. * Custom error thrown after attach/detach if one or more behaviors failed.
  78. * Initializes the JavaScript behaviors for page loads and Ajax requests.
  79. *
  80. * @callback Drupal~behaviorAttach
  81. *
  82. * @param {HTMLDocument|HTMLElement} context
  83. * An element to detach behaviors from.
  84. * @param {?object} settings
  85. * An object containing settings for the current context. It is rarely used.
  86. *
  87. * @see Drupal.attachBehaviors
  88. */
  89. /**
  90. * Reverts and cleans up JavaScript behavior initialization.
  91. *
  92. * @callback Drupal~behaviorDetach
  93. *
  94. * @param {HTMLDocument|HTMLElement} context
  95. * An element to attach behaviors to.
  96. * @param {object} settings
  97. * An object containing settings for the current context.
  98. * @param {string} trigger
  99. * One of `'unload'`, `'move'`, or `'serialize'`.
  100. *
  101. * @see Drupal.detachBehaviors
  102. */
  103. /**
  104. * @typedef {object} Drupal~behavior
  105. *
  106. * @prop {Drupal~behaviorAttach} attach
  107. * Function run on page load and after an Ajax call.
  108. * @prop {Drupal~behaviorDetach} detach
  109. * Function run when content is serialized or removed from the page.
  110. */
  111. /**
  112. * Holds all initialization methods.
  113. *
  114. * @namespace Drupal.behaviors
  115. *
  116. * @type {Object.<string, Drupal~behavior>}
  117. */
  118. /**
  119. * Defines a behavior to be run during attach and detach phases.
  120. *
  121. * Attaches all registered behaviors to a page element.
  122. *
  123. * Behaviors are event-triggered actions that attach to page elements,
  124. * enhancing default non-JavaScript UIs. Behaviors are registered in the
  125. * {@link Drupal.behaviors} object using the method 'attach' and optionally
  126. * also 'detach'.
  127. *
  128. * {@link Drupal.attachBehaviors} is added below to the `jQuery.ready` event
  129. * and therefore runs on initial page load. Developers implementing Ajax in
  130. * their solutions should also call this function after new page content has
  131. * been loaded, feeding in an element to be processed, in order to attach all
  132. * behaviors to the new content.
  133. *
  134. * Behaviors should use `var elements =
  135. * $(context).find(selector).once('behavior-name');` to ensure the behavior is
  136. * attached only once to a given element. (Doing so enables the reprocessing
  137. * of given elements, which may be needed on occasion despite the ability to
  138. * limit behavior attachment to a particular element.)
  139. *
  140. * @example
  141. * Drupal.behaviors.behaviorName = {
  142. * attach: function (context, settings) {
  143. * // ...
  144. * },
  145. * detach: function (context, settings, trigger) {
  146. * // ...
  147. * }
  148. * };
  149. *
  150. * @param {HTMLDocument|HTMLElement} [context=document]
  151. * An element to attach behaviors to.
  152. * @param {object} [settings=drupalSettings]
  153. * An object containing settings for the current context. If none is given,
  154. * the global {@link drupalSettings} object is used.
  155. *
  156. * @see Drupal~behaviorAttach
  157. * @see Drupal.detachBehaviors
  158. *
  159. * @throws {Drupal~DrupalBehaviorError}
  160. */
  161. Drupal.attachBehaviors = function (context, settings) {
  162. context = context || document;
  163. settings = settings || drupalSettings;
  164. var behaviors = Drupal.behaviors;
  165. // Execute all of them.
  166. for (var i in behaviors) {
  167. if (behaviors.hasOwnProperty(i) && typeof behaviors[i].attach === 'function') {
  168. // Don't stop the execution of behaviors in case of an error.
  169. try {
  170. behaviors[i].attach(context, settings);
  171. }
  172. catch (e) {
  173. Drupal.throwError(e);
  174. }
  175. }
  176. }
  177. };
  178. /**
  179. * Detaches registered behaviors from a page element.
  180. *
  181. * Developers implementing Ajax in their solutions should call this function
  182. * before page content is about to be removed, feeding in an element to be
  183. * processed, in order to allow special behaviors to detach from the content.
  184. *
  185. * Such implementations should use `.findOnce()` and `.removeOnce()` to find
  186. * elements with their corresponding `Drupal.behaviors.behaviorName.attach`
  187. * implementation, i.e. `.removeOnce('behaviorName')`, to ensure the behavior
  188. * is detached only from previously processed elements.
  189. *
  190. * @param {HTMLDocument|HTMLElement} [context=document]
  191. * An element to detach behaviors from.
  192. * @param {object} [settings=drupalSettings]
  193. * An object containing settings for the current context. If none given,
  194. * the global {@link drupalSettings} object is used.
  195. * @param {string} [trigger='unload']
  196. * A string containing what's causing the behaviors to be detached. The
  197. * possible triggers are:
  198. * - `'unload'`: The context element is being removed from the DOM.
  199. * - `'move'`: The element is about to be moved within the DOM (for example,
  200. * during a tabledrag row swap). After the move is completed,
  201. * {@link Drupal.attachBehaviors} is called, so that the behavior can undo
  202. * whatever it did in response to the move. Many behaviors won't need to
  203. * do anything simply in response to the element being moved, but because
  204. * IFRAME elements reload their "src" when being moved within the DOM,
  205. * behaviors bound to IFRAME elements (like WYSIWYG editors) may need to
  206. * take some action.
  207. * - `'serialize'`: When an Ajax form is submitted, this is called with the
  208. * form as the context. This provides every behavior within the form an
  209. * opportunity to ensure that the field elements have correct content
  210. * in them before the form is serialized. The canonical use-case is so
  211. * that WYSIWYG editors can update the hidden textarea to which they are
  212. * bound.
  213. *
  214. * @throws {Drupal~DrupalBehaviorError}
  215. *
  216. * @see Drupal~behaviorDetach
  217. * @see Drupal.attachBehaviors
  218. */
  219. Drupal.detachBehaviors = function (context, settings, trigger) {
  220. context = context || document;
  221. settings = settings || drupalSettings;
  222. trigger = trigger || 'unload';
  223. var behaviors = Drupal.behaviors;
  224. // Execute all of them.
  225. for (var i in behaviors) {
  226. if (behaviors.hasOwnProperty(i) && typeof behaviors[i].detach === 'function') {
  227. // Don't stop the execution of behaviors in case of an error.
  228. try {
  229. behaviors[i].detach(context, settings, trigger);
  230. }
  231. catch (e) {
  232. Drupal.throwError(e);
  233. }
  234. }
  235. }
  236. };
  237. /**
  238. * Encodes special characters in a plain-text string for display as HTML.
  239. *
  240. * @param {string} str
  241. * The string to be encoded.
  242. *
  243. * @return {string}
  244. * The encoded string.
  245. *
  246. * @ingroup sanitization
  247. */
  248. Drupal.checkPlain = function (str) {
  249. str = str.toString()
  250. .replace(/&/g, '&amp;')
  251. .replace(/"/g, '&quot;')
  252. .replace(/</g, '&lt;')
  253. .replace(/>/g, '&gt;');
  254. return str;
  255. };
  256. /**
  257. * Replaces placeholders with sanitized values in a string.
  258. *
  259. * @param {string} str
  260. * A string with placeholders.
  261. * @param {object} args
  262. * An object of replacements pairs to make. Incidences of any key in this
  263. * array are replaced with the corresponding value. Based on the first
  264. * character of the key, the value is escaped and/or themed:
  265. * - `'!variable'`: inserted as is.
  266. * - `'@variable'`: escape plain text to HTML ({@link Drupal.checkPlain}).
  267. * - `'%variable'`: escape text and theme as a placeholder for user-
  268. * submitted content ({@link Drupal.checkPlain} +
  269. * `{@link Drupal.theme}('placeholder')`).
  270. *
  271. * @return {string}
  272. * The formatted string.
  273. *
  274. * @see Drupal.t
  275. */
  276. Drupal.formatString = function (str, args) {
  277. // Keep args intact.
  278. var processedArgs = {};
  279. // Transform arguments before inserting them.
  280. for (var key in args) {
  281. if (args.hasOwnProperty(key)) {
  282. switch (key.charAt(0)) {
  283. // Escaped only.
  284. case '@':
  285. processedArgs[key] = Drupal.checkPlain(args[key]);
  286. break;
  287. // Pass-through.
  288. case '!':
  289. processedArgs[key] = args[key];
  290. break;
  291. // Escaped and placeholder.
  292. default:
  293. processedArgs[key] = Drupal.theme('placeholder', args[key]);
  294. break;
  295. }
  296. }
  297. }
  298. return Drupal.stringReplace(str, processedArgs, null);
  299. };
  300. /**
  301. * Replaces substring.
  302. *
  303. * The longest keys will be tried first. Once a substring has been replaced,
  304. * its new value will not be searched again.
  305. *
  306. * @param {string} str
  307. * A string with placeholders.
  308. * @param {object} args
  309. * Key-value pairs.
  310. * @param {Array|null} keys
  311. * Array of keys from `args`. Internal use only.
  312. *
  313. * @return {string}
  314. * The replaced string.
  315. */
  316. Drupal.stringReplace = function (str, args, keys) {
  317. if (str.length === 0) {
  318. return str;
  319. }
  320. // If the array of keys is not passed then collect the keys from the args.
  321. if (!Array.isArray(keys)) {
  322. keys = [];
  323. for (var k in args) {
  324. if (args.hasOwnProperty(k)) {
  325. keys.push(k);
  326. }
  327. }
  328. // Order the keys by the character length. The shortest one is the first.
  329. keys.sort(function (a, b) { return a.length - b.length; });
  330. }
  331. if (keys.length === 0) {
  332. return str;
  333. }
  334. // Take next longest one from the end.
  335. var key = keys.pop();
  336. var fragments = str.split(key);
  337. if (keys.length) {
  338. for (var i = 0; i < fragments.length; i++) {
  339. // Process each fragment with a copy of remaining keys.
  340. fragments[i] = Drupal.stringReplace(fragments[i], args, keys.slice(0));
  341. }
  342. }
  343. return fragments.join(args[key]);
  344. };
  345. /**
  346. * Translates strings to the page language, or a given language.
  347. *
  348. * See the documentation of the server-side t() function for further details.
  349. *
  350. * @param {string} str
  351. * A string containing the English text to translate.
  352. * @param {Object.<string, string>} [args]
  353. * An object of replacements pairs to make after translation. Incidences
  354. * of any key in this array are replaced with the corresponding value.
  355. * See {@link Drupal.formatString}.
  356. * @param {object} [options]
  357. * Additional options for translation.
  358. * @param {string} [options.context='']
  359. * The context the source string belongs to.
  360. *
  361. * @return {string}
  362. * The formatted string.
  363. * The translated string.
  364. */
  365. Drupal.t = function (str, args, options) {
  366. options = options || {};
  367. options.context = options.context || '';
  368. // Fetch the localized version of the string.
  369. if (typeof drupalTranslations !== 'undefined' && drupalTranslations.strings && drupalTranslations.strings[options.context] && drupalTranslations.strings[options.context][str]) {
  370. str = drupalTranslations.strings[options.context][str];
  371. }
  372. if (args) {
  373. str = Drupal.formatString(str, args);
  374. }
  375. return str;
  376. };
  377. /**
  378. * Returns the URL to a Drupal page.
  379. *
  380. * @param {string} path
  381. * Drupal path to transform to URL.
  382. *
  383. * @return {string}
  384. * The full URL.
  385. */
  386. Drupal.url = function (path) {
  387. return drupalSettings.path.baseUrl + drupalSettings.path.pathPrefix + path;
  388. };
  389. /**
  390. * Returns the passed in URL as an absolute URL.
  391. *
  392. * @param {string} url
  393. * The URL string to be normalized to an absolute URL.
  394. *
  395. * @return {string}
  396. * The normalized, absolute URL.
  397. *
  398. * @see https://github.com/angular/angular.js/blob/v1.4.4/src/ng/urlUtils.js
  399. * @see https://grack.com/blog/2009/11/17/absolutizing-url-in-javascript
  400. * @see https://github.com/jquery/jquery-ui/blob/1.11.4/ui/tabs.js#L53
  401. */
  402. Drupal.url.toAbsolute = function (url) {
  403. var urlParsingNode = document.createElement('a');
  404. // Decode the URL first; this is required by IE <= 6. Decoding non-UTF-8
  405. // strings may throw an exception.
  406. try {
  407. url = decodeURIComponent(url);
  408. }
  409. catch (e) {
  410. // Empty.
  411. }
  412. urlParsingNode.setAttribute('href', url);
  413. // IE <= 7 normalizes the URL when assigned to the anchor node similar to
  414. // the other browsers.
  415. return urlParsingNode.cloneNode(false).href;
  416. };
  417. /**
  418. * Returns true if the URL is within Drupal's base path.
  419. *
  420. * @param {string} url
  421. * The URL string to be tested.
  422. *
  423. * @return {bool}
  424. * `true` if local.
  425. *
  426. * @see https://github.com/jquery/jquery-ui/blob/1.11.4/ui/tabs.js#L58
  427. */
  428. Drupal.url.isLocal = function (url) {
  429. // Always use browser-derived absolute URLs in the comparison, to avoid
  430. // attempts to break out of the base path using directory traversal.
  431. var absoluteUrl = Drupal.url.toAbsolute(url);
  432. var protocol = location.protocol;
  433. // Consider URLs that match this site's base URL but use HTTPS instead of HTTP
  434. // as local as well.
  435. if (protocol === 'http:' && absoluteUrl.indexOf('https:') === 0) {
  436. protocol = 'https:';
  437. }
  438. var baseUrl = protocol + '//' + location.host + drupalSettings.path.baseUrl.slice(0, -1);
  439. // Decoding non-UTF-8 strings may throw an exception.
  440. try {
  441. absoluteUrl = decodeURIComponent(absoluteUrl);
  442. }
  443. catch (e) {
  444. // Empty.
  445. }
  446. try {
  447. baseUrl = decodeURIComponent(baseUrl);
  448. }
  449. catch (e) {
  450. // Empty.
  451. }
  452. // The given URL matches the site's base URL, or has a path under the site's
  453. // base URL.
  454. return absoluteUrl === baseUrl || absoluteUrl.indexOf(baseUrl + '/') === 0;
  455. };
  456. /**
  457. * Formats a string containing a count of items.
  458. *
  459. * This function ensures that the string is pluralized correctly. Since
  460. * {@link Drupal.t} is called by this function, make sure not to pass
  461. * already-localized strings to it.
  462. *
  463. * See the documentation of the server-side
  464. * \Drupal\Core\StringTranslation\TranslationInterface::formatPlural()
  465. * function for more details.
  466. *
  467. * @param {number} count
  468. * The item count to display.
  469. * @param {string} singular
  470. * The string for the singular case. Please make sure it is clear this is
  471. * singular, to ease translation (e.g. use "1 new comment" instead of "1
  472. * new"). Do not use @count in the singular string.
  473. * @param {string} plural
  474. * The string for the plural case. Please make sure it is clear this is
  475. * plural, to ease translation. Use @count in place of the item count, as in
  476. * "@count new comments".
  477. * @param {object} [args]
  478. * An object of replacements pairs to make after translation. Incidences
  479. * of any key in this array are replaced with the corresponding value.
  480. * See {@link Drupal.formatString}.
  481. * Note that you do not need to include @count in this array.
  482. * This replacement is done automatically for the plural case.
  483. * @param {object} [options]
  484. * The options to pass to the {@link Drupal.t} function.
  485. *
  486. * @return {string}
  487. * A translated string.
  488. */
  489. Drupal.formatPlural = function (count, singular, plural, args, options) {
  490. args = args || {};
  491. args['@count'] = count;
  492. var pluralDelimiter = drupalSettings.pluralDelimiter;
  493. var translations = Drupal.t(singular + pluralDelimiter + plural, args, options).split(pluralDelimiter);
  494. var index = 0;
  495. // Determine the index of the plural form.
  496. if (typeof drupalTranslations !== 'undefined' && drupalTranslations.pluralFormula) {
  497. index = count in drupalTranslations.pluralFormula ? drupalTranslations.pluralFormula[count] : drupalTranslations.pluralFormula['default'];
  498. }
  499. else if (args['@count'] !== 1) {
  500. index = 1;
  501. }
  502. return translations[index];
  503. };
  504. /**
  505. * Encodes a Drupal path for use in a URL.
  506. *
  507. * For aesthetic reasons slashes are not escaped.
  508. *
  509. * @param {string} item
  510. * Unencoded path.
  511. *
  512. * @return {string}
  513. * The encoded path.
  514. */
  515. Drupal.encodePath = function (item) {
  516. return window.encodeURIComponent(item).replace(/%2F/g, '/');
  517. };
  518. /**
  519. * Generates the themed representation of a Drupal object.
  520. *
  521. * All requests for themed output must go through this function. It examines
  522. * the request and routes it to the appropriate theme function. If the current
  523. * theme does not provide an override function, the generic theme function is
  524. * called.
  525. *
  526. * @example
  527. * <caption>To retrieve the HTML for text that should be emphasized and
  528. * displayed as a placeholder inside a sentence.</caption>
  529. * Drupal.theme('placeholder', text);
  530. *
  531. * @namespace
  532. *
  533. * @param {function} func
  534. * The name of the theme function to call.
  535. * @param {...args}
  536. * Additional arguments to pass along to the theme function.
  537. *
  538. * @return {string|object|HTMLElement|jQuery}
  539. * Any data the theme function returns. This could be a plain HTML string,
  540. * but also a complex object.
  541. */
  542. Drupal.theme = function (func) {
  543. var args = Array.prototype.slice.apply(arguments, [1]);
  544. if (func in Drupal.theme) {
  545. return Drupal.theme[func].apply(this, args);
  546. }
  547. };
  548. /**
  549. * Formats text for emphasized display in a placeholder inside a sentence.
  550. *
  551. * @param {string} str
  552. * The text to format (plain-text).
  553. *
  554. * @return {string}
  555. * The formatted text (html).
  556. */
  557. Drupal.theme.placeholder = function (str) {
  558. return '<em class="placeholder">' + Drupal.checkPlain(str) + '</em>';
  559. };
  560. })(Drupal, window.drupalSettings, window.drupalTranslations);
  561. ;
  562. // Allow other JavaScript libraries to use $.
  563. if (window.jQuery) {
  564. jQuery.noConflict();
  565. }
  566. // Class indicating that JS is enabled; used for styling purpose.
  567. document.documentElement.className += ' js';
  568. // JavaScript should be made compatible with libraries other than jQuery by
  569. // wrapping it in an anonymous closure.
  570. (function (domready, Drupal, drupalSettings) {
  571. 'use strict';
  572. // Attach all behaviors.
  573. domready(function () { Drupal.attachBehaviors(document, drupalSettings); });
  574. })(domready, Drupal, window.drupalSettings);
  575. ;
  576. /**
  577. * @file
  578. * Attaches behaviors for Drupal's active link marking.
  579. */
  580. (function (Drupal, drupalSettings) {
  581. 'use strict';
  582. /**
  583. * Append is-active class.
  584. *
  585. * The link is only active if its path corresponds to the current path, the
  586. * language of the linked path is equal to the current language, and if the
  587. * query parameters of the link equal those of the current request, since the
  588. * same request with different query parameters may yield a different page
  589. * (e.g. pagers, exposed View filters).
  590. *
  591. * Does not discriminate based on element type, so allows you to set the
  592. * is-active class on any element: a, li…
  593. *
  594. * @type {Drupal~behavior}
  595. */
  596. Drupal.behaviors.activeLinks = {
  597. attach: function (context) {
  598. // Start by finding all potentially active links.
  599. var path = drupalSettings.path;
  600. var queryString = JSON.stringify(path.currentQuery);
  601. var querySelector = path.currentQuery ? "[data-drupal-link-query='" + queryString + "']" : ':not([data-drupal-link-query])';
  602. var originalSelectors = ['[data-drupal-link-system-path="' + path.currentPath + '"]'];
  603. var selectors;
  604. // If this is the front page, we have to check for the <front> path as
  605. // well.
  606. if (path.isFront) {
  607. originalSelectors.push('[data-drupal-link-system-path="<front>"]');
  608. }
  609. // Add language filtering.
  610. selectors = [].concat(
  611. // Links without any hreflang attributes (most of them).
  612. originalSelectors.map(function (selector) { return selector + ':not([hreflang])'; }),
  613. // Links with hreflang equals to the current language.
  614. originalSelectors.map(function (selector) { return selector + '[hreflang="' + path.currentLanguage + '"]'; })
  615. );
  616. // Add query string selector for pagers, exposed filters.
  617. selectors = selectors.map(function (current) { return current + querySelector; });
  618. // Query the DOM.
  619. var activeLinks = context.querySelectorAll(selectors.join(','));
  620. var il = activeLinks.length;
  621. for (var i = 0; i < il; i++) {
  622. activeLinks[i].classList.add('is-active');
  623. }
  624. },
  625. detach: function (context, settings, trigger) {
  626. if (trigger === 'unload') {
  627. var activeLinks = context.querySelectorAll('[data-drupal-link-system-path].is-active');
  628. var il = activeLinks.length;
  629. for (var i = 0; i < il; i++) {
  630. activeLinks[i].classList.remove('is-active');
  631. }
  632. }
  633. }
  634. };
  635. })(Drupal, drupalSettings);
  636. ;