PageSourceSearch

https://www.justformen.com/sites/g/files/sgirzt191/files/js/optimi…2vxetfVgl2z03JVQwTkFtKuHtbZwmI.js?v=10.6.15

js justformen.com collected 2026-09-26 02:10:43 UTC 21,309 bytes, 688 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.