PageSourceSearch

https://portableapps.com/files/advagg_js/js__Xi0O1N6gYQt5QUJH9KUJK…CpYCUG_v4bdSNPKqL0juJ_tf8QOxUMLlOZ4KGFKw.js

js portableapps.com collected 2026-10-01 08:33:58 UTC 40,104 bytes, 1,095 lines download raw bytes

1/**
2 * For jQuery versions less than 3.4.0, this replaces the jQuery.extend
3 * function with the one from jQuery 3.4.0, slightly modified (documented
4 * below) to be compatible with older jQuery versions and browsers.
5 *
6 * This provides the Object.prototype pollution vulnerability fix to Drupal
7 * installations running older jQuery versions, including the versions shipped
8 * with Drupal core and https://www.drupal.org/project/jquery_update.
9 *
10 * @see https://github.com/jquery/jquery/pull/4333
11 */
12
13(function (jQuery) {
14
15// Do not override jQuery.extend() if the jQuery version is already >=3.4.0.
16var versionParts = jQuery.fn.jquery.split('.');
17var majorVersion = parseInt(versionParts[0]);
18var minorVersion = parseInt(versionParts[1]);
19var patchVersion = parseInt(versionParts[2]);
20var isPreReleaseVersion = (patchVersion.toString() !== versionParts[2]);
21if (
22  (majorVersion > 3) ||
23  (majorVersion === 3 && minorVersion > 4) ||
24  (majorVersion === 3 && minorVersion === 4 && patchVersion > 0) ||
25  (majorVersion === 3 && minorVersion === 4 && patchVersion === 0 && !isPreReleaseVersion)
26) {
27  return;
28}
29
30/**
31 * This is almost verbatim copied from jQuery 3.4.0.
32 *
33 * Only two minor changes have been made:
34 * - The call to isFunction() is changed to jQuery.isFunction().
35 * - The two calls to Array.isArray() is changed to jQuery.isArray().
36 *
37 * The above two changes ensure compatibility with all older jQuery versions
38 * (1.4.4 - 3.3.1) and older browser versions (e.g., IE8).
39 */
40jQuery.extend = jQuery.fn.extend = function() {
41  var options, name, src, copy, copyIsArray, clone,
42    target = arguments[ 0 ] || {},
43    i = 1,
44    length = arguments.length,
45    deep = false;
46
47  // Handle a deep copy situation
48  if ( typeof target === "boolean" ) {
49    deep = target;
50
51    // Skip the boolean and the target
52    target = arguments[ i ] || {};
53    i++;
54  }
55
56  // Handle case when target is a string or something (possible in deep copy)
57  if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
58    target = {};
59  }
60
61  // Extend jQuery itself if only one argument is passed
62  if ( i === length ) {
63    target = this;
64    i--;
65  }
66
67  for ( ; i < length; i++ ) {
68
69    // Only deal with non-null/undefined values
70    if ( ( options = arguments[ i ] ) != null ) {
71
72      // Extend the base object
73      for ( name in options ) {
74        copy = options[ name ];
75
76        // Prevent Object.prototype pollution
77        // Prevent never-ending loop
78        if ( name === "__proto__" || target === copy ) {
79          continue;
80        }
81
82        // Recurse if we're merging plain objects or arrays
83        if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
84          ( copyIsArray = jQuery.isArray( copy ) ) ) ) {
85          src = target[ name ];
86
87          // Ensure proper type for the source value
88          if ( copyIsArray && !jQuery.isArray( src ) ) {
89            clone = [];
90          } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) {
91            clone = {};
92          } else {
93            clone = src;
94          }
95          copyIsArray = false;
96
97          // Never move original objects, clone them
98          target[ name ] = jQuery.extend( deep, clone, copy );
99
100          // Don't bring in undefined values
101        } else if ( copy !== undefined ) {
102          target[ name ] = copy;
103        }
104      }
105    }
106  }
107
108  // Return the modified object
109  return target;
110};
111
112})(jQuery);
113;/*})'"*/;/*})'"*/
114/**
115 * For jQuery versions less than 3.5.0, this replaces the jQuery.htmlPrefilter()
116 * function with one that fixes these security vulnerabilities while also
117 * retaining the pre-3.5.0 behavior where it's safe to do so.
118 * - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11022
119 * - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11023
120 *
121 * Additionally, for jQuery versions that do not have a jQuery.htmlPrefilter()
122 * function (1.x prior to 1.12 and 2.x prior to 2.2), this adds it, and
123 * extends the functions that need to call it to do so.
124 *
125 * Drupal core's jQuery version is 1.4.4, but jQuery Update can provide a
126 * different version, so this covers all versions between 1.4.4 and 3.4.1.
127 * The GitHub links in the code comments below link to jQuery 1.5 code, be
127cause
128 * 1.4.4 isn't on GitHub, but the referenced code didn't change from 1.4.4 to
129 * 1.5.
130 */
131
132(function (jQuery) {
133
134  // Parts of this backport differ by jQuery version.
135  var versionParts = jQuery.fn.jquery.split('.');
136  var majorVersion = parseInt(versionParts[0]);
137  var minorVersion = parseInt(versionParts[1]);
138
139  // No backport is needed if we're already on jQuery 3.5 or higher.
140  if ( (majorVersion > 3) || (majorVersion === 3 && minorVersion >= 5) ) {
141    return;
142  }
143
144  // Prior to jQuery 3.5, jQuery converted XHTML-style self-closing tags to
145  // their XML equivalent: e.g., "<div />" to "<div></div>". This is
146  // problematic for several reasons, including that it's vulnerable to XSS
147  // attacks. However, since this was jQuery's behavior for many years, many
148  // Drupal modules and jQuery plugins may be relying on it. Therefore, we
149  // preserve that behavior, but for a limited set of tags only, that we believe
150  // to not be vulnerable. This is the set of HTML tags that satisfy all of the
151  // following conditions:
152  // - In DOMPurify's list of HTML tags. If an HTML tag isn't safe enough to
153  //   appear in that list, then we don't want to mess with it here either.
154  //   @see https://github.com/cure53/DOMPurify/blob/2.0.11/dist/purify.js#L128
155  // - A normal element (not a void, template, text, or foreign element).
156  //   @see https://html.spec.whatwg.org/multipage/syntax.html#elements-2
157  // - An element that is still defined by the current HTML specification
158  //   (not a deprecated element), because we do not want to rely on how
159  //   browsers parse deprecated elements.
160  //   @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element
161  // - Not 'html', 'head', or 'body', because this pseudo-XHTML expansion is
162  //   designed for fragments, not entire documents.
163  // - Not 'colgroup', because due to an idiosyncrasy of jQuery's original
164  //   regular expression, it didn't match on colgroup, and we don't want to
165  //   introduce a behavior change for that.
166  var selfClosingTagsToReplace = [
167    'a', 'abbr', 'address', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo',
168    'blockquote', 'button', 'canvas', 'caption', 'cite', 'code', 'data',
169    'datalist', 'dd', 'del', 'details', 'dfn', 'div', 'dl', 'dt', 'em',
170    'fieldset', 'figcaption', 'figure', 'footer', 'form', 'h1', 'h2', 'h3',
171    'h4', 'h5', 'h6', 'header', 'hgroup', 'i', 'ins', 'kbd', 'label', 'legend',
172    'li', 'main', 'map', 'mark', 'menu', 'meter', 'nav', 'ol', 'optgroup',
173    'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt',
174    'ruby', 's', 'samp', 'section', 'select', 'small', 'source', 'span',
175    'strong', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'tfoot', 'th',
176    'thead', 'time', 'tr', 'u', 'ul', 'var', 'video'
177  ];
178
179  // Define regular expressions for <TAG/> and <TAG ATTRIBUTES/>. Doing this as
180  // two expressions makes it easier to target <a/> without also targeting
181  // every tag that starts with "a".
182  var xhtmlRegExpGroup = '(' + selfClosingTagsToReplace.join('|') + ')';
183  var whitespace = '[\\x20\\t\\r\\n\\f]';
184  var rxhtmlTagWithoutSpaceOrAttributes = new RegExp('<' + xhtmlRegExpGroup + '\\/>', 'gi');
185  var rxhtmlTagWithSpaceAndMaybeAttributes = new RegExp('<' + xhtmlRegExpGroup + '(' + whitespace + '[^>]*)\\/>', 'gi');
186
187  // jQuery 3.5 also fixed a vulnerability for when </select> appears within
188  // an <option> or <optgroup>, but it did that in local code that we can't
189  // backport directly. Instead, we filter such cases out. To do so, we need to
190  // determine when jQuery would otherwise invoke the vulnerable code, which it
191  // uses this regular expression to determine. The regular expression changed
192  // for version 3.0.0 and changed again for 3.4.0.
193  // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L4958
194  // @see https://github.com/jquery/jquery/blob/3.0.0/dist/jquery.js#L4584
195  // @see https://github.com/jquery/jquery/blob/3.4.0/dist/jquery.js#L4712
196  var rtagName;
197  if (majorVersion < 3) {
198    rtagName = /<([\w:]+)/;
199  }
200  else if (minorVersion < 4) {
201    rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]+)/i;
202  }
203  else {
204    rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i;
205  }
206
207  // The regular expression that jQuery uses to determine which self-closing
208  // tags to expand to open and close tags. This is vulnerable, because it
209  // matches all tag names except the few excluded ones. We only use this
210  // expression for determining vulnerability. The expression changed for
211  // version 3, but we only need to check for vulnerability in versions 1 and 2,
212  // so we use the expression from those versions.
213  // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L4957
214  var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi;
215
216  jQuery.extend({
217    htmlPrefilter: function (html) {
218      // This is how jQuery determines the first tag in the HTML.
219      // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5521
220      var tag = ( rtagName.exec( html ) || [ "", "" ] )[ 1 ].toLowerCase();
221
222      // It is not valid HTML for <option> or <optgroup> to have <select> as
223      // either a descendant or sibling, and attempts to inject one can cause
224      // XSS on jQuery versions before 3.5. Since this is invalid HTML and a
225      // possible XSS attack, reject the entire string.
226      // @see https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11023
227      if ((tag === 'option' || tag === 'optgroup') && html.match(/<\/?select/i)) {
228        html = '';
229      }
230
231      // Retain jQuery's prior to 3.5 conversion of pseudo-XHTML, but for only
232      // the tags in the `selfClosingTagsToReplace` list defined above.
233      // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5518
234      // @see https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-11022
235      html = html.replace(rxhtmlTagWithoutSpaceOrAttributes, "<$1></$1>");
236      html = html.replace(rxhtmlTagWithSpaceAndMaybeAttributes, "<$1$2></$1>");
237
238      // Prior to jQuery 1.12 and 2.2, this function gets called (via code later
239      // in this file) in addition to, rather than instead of, the unsafe
240      // expansion of self-closing tags (including ones not in the list above).
241      // We can't prevent that unsafe expansion from running, so instead we
242      // check to make sure that it doesn't affect the DOM returned by the
243      // browser's parsing logic. If it does affect it, then it's vulnerable to
244      // XSS, so we reject the entire string.
245      if ( (majorVersion === 1 && minorVersion < 12) || (majorVersion === 2 && minorVersion < 2) ) {
246        var htmlRisky = html.replace(rxhtmlTag, "<$1></$2>");
247        if (htmlRisky !== html) {
248          // Even though htmlRisky and html are different strings, they might
249          // represent the same HTML structure once parsed, in which case,
250          // htmlRisky is actually safe. We can ask the browser to parse both
251          // to find out, but the browser can't parse table fragments (e.g., a
252          // root-level "<td>"), so we need to wrap them. We just need this
253          // technique to work on all supported browsers; we don't need to
254          // copy from the specific jQuery version we're using.
255          // @see https://github.com/jquery/jquery/blob/3.5.1/dist/jquery.js#L4939
256          var wrapMap = {
257            thead: [ 1, "<table>", "</table>" ],
258            col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
259            tr: [ 2, "<table><tbody>", "</tbody></table>" ],
260            td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
261          };
262          wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
263          wrapMap.th = wrapMap.td;
264
265          // Function to wrap HTML into something that a browser can parse.
266          // @see https://github.com/jquery/jquery/blob/3.5.1/dist/jquery.js#L5032
267          var getWrappedHtml = function (html) {
268            var wrap = wrapMap[tag];
269            if (wrap) {
270              html = wrap[1] + html + wrap[2];
271            }
272            return html;
273          };
274
275          // Function to return canonical HTML after parsing it. This parses
276          // only; it doesn't execute scripts.
277          // @see https://github.com/jquery/jquery-migrate/blob/3.3.0/src/jquery/manipulation.js#L5
278          var getParsedHtml = function (html) {
279            var doc = window.document.implementation.createHTMLDocument( "" );
280            doc.body.innerHTML = html;
281            return doc.body ? doc.body.innerHTML : '';
282          };
283
284          // If the browser couldn't parse either one successfully, or if
285          // htmlRisky parses differently than html, then html is vulnerable,
286          // so reject it.
287          var htmlParsed = getParsedHtml(getWrappedHtml(html));
288          var htmlRiskyParsed = getParsedHtml(getWrappedHtml(htmlRisky));
289          if (htmlRiskyParsed === '' || htmlParsed === '' || (htmlRiskyParsed !== htmlParsed)) {
290            html = '';
291          }
292        }
293      }
294
295      return html;
296    }
297  });
298
299  // Prior to jQuery 1.12 and 2.2, jQuery.clean(), jQuery.buildFragment(), and
300  // jQuery.fn.html() did not call jQuery.htmlPrefilter(), so we add that.
301  if ( (majorVersion === 1 && minorVersion < 12) || (majorVersion === 2 && minorVersion < 2) ) {
302    // Filter the HTML coming into jQuery.fn.html().
303    var fnOriginalHtml = jQuery.fn.html;
304    jQuery.fn.extend({
305      // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5147
306      html: function (value) {
307        if (typeof value === "string") {
308          value = jQuery.htmlPrefilter(value);
309        }
310        // .html() can be called as a setter (with an argument) or as a getter
311        // (without an argument), so invoke fnOriginalHtml() the same way that
312        // we were invoked.
313        return fnOriginalHtml.apply(this, arguments.length ? [value] : []);
314      }
315    });
316
317    // The regular expression that jQuery uses to determine if a string is HTML.
318    // Used by both clean() and buildFragment().
319    // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L4960
320    var rhtml = /<|&#?\w+;/;
321
322    // Filter HTML coming into:
323    // - jQuery.clean() for versions prior to 1.9.
324    // - jQuery.buildFragment() for 1.9 and above.
325    //
326    // The looping constructs in the two functions might be essentially
327    // identical, but they're each expressed here in the way that most closely
328    // matches their original expression in jQuery, so that we filter all of
329    // the items and only the items that jQuery will treat as HTML strings.
330    if (majorVersion === 1 && minorVersion < 9) {
331      var originalClean = jQuery.clean;
332      jQuery.extend({
333        // @see https://github.com/jquery/jquery/blob/1.5/jquery.js#L5493
334        'clean': function (elems, context, fragment, scripts) {
335          for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
336            if ( typeof elem === "string" && rhtml.test( elem ) ) {
337              elems[i] = elem = jQuery.htmlPrefilter(elem);
338            }
339          }
340          return originalClean.call(this, elems, context, fragment, scripts);
341        }
342      });
343    }
344    else {
345      var originalBuildFragment = jQuery.buildFragment;
346      jQuery.extend({
347        // @see https://github.com/jquery/jquery/blob/1.9.0/jquery.js#L6419
348        'buildFragment': function (elems, context, scripts, selection) {
349          var l = elems.length;
350          for ( var i = 0; i < l; i++ ) {
351            var elem = elems[i];
352            if (elem || elem === 0) {
353              if ( jQuery.type( elem ) !== "object" && rhtml.test( elem ) ) {
354                elems[i] = elem = jQuery.htmlPrefilter(elem);
355              }
356            }
357          }
358          return originalBuildFragment.call(this, elems, context, scripts, selection);
359        }
360      });
361    }
362  }
363
364})(jQuery);
365;/*})'"*/;/*})'"*/
366/**
367 * jQuery Once Plugin v1.2
368 * http://plugins.jquery.com/project/once
369 *
370 * Dual licensed under the MIT and GPL licenses:
371 *   http://www.opensource.org/licenses/mit-license.php
372 *   http://www.gnu.org/licenses/gpl.html
373 */
374
375(function ($) {
376  var cache = {}, uuid = 0;
377
378  /**
379   * Filters elements by whether they have not yet been processed.
380   *
381   * @param id
382   *   (Optional) If this is a string, then it will be used as the CSS class
383   *   name that is applied to the elements for determining whether it has
384   *   already been processed. The elements will get a class in the form of
385   *   "id-processed".
386   *
387   *   If the id parameter is a function, it will be passed off to the fn
388   *   parameter and the id will become a unique identifier, represented as a
389   *   number.
390   *
391   *   When the id is neither a string or a function, it becomes a unique
392   *   identifier, depicted as a number. The element's class will then be
393   *   represented in the form of "jquery-once-#-processed".
394   *
395   *   Take note that the id must be valid for usage as an element's class name.
396   * @param fn
397   *   (Optional) If given, this function will be called for each element that
398   *   has not yet been processed. The function's return value follows the same
399   *   logic as $.each(). Returning true will continue to the next matched
400   *   element in the set, while returning false will entirely break the
401   *   iteration.
402   */
403  $.fn.once = function (id, fn) {
404    if (typeof id != 'string') {
405      // Generate a numeric ID if the id passed can't be used as a CSS class.
406      if (!(id in cache)) {
407        cache[id] = ++uuid;
408      }
409      // When the fn parameter is not passed, we interpret it from the id.
410      if (!fn) {
411        fn = id;
412      }
413      id = 'jquery-once-' + cache[id];
414    }
415    // Remove elements from the set that have already been processed.
416    var name = id + '-processed';
417    var elements = this.not('.' + name).addClass(name);
418
419    return $.isFunction(fn) ? elements.each(fn) : elements;
420  };
421
422  /**
423   * Filters elements that have been processed once already.
424   *
425   * @param id
426   *   A required string representing the name of the class which should be used
427   *   when filtering the elements. This only filters elements that have already
428   *   been processed by the once function. The id should be the same id that
429   *   was originally passed to the once() function.
430   * @param fn
431   *   (Optional) If given, this function will be called for each element that
432   *   has not yet been processed. The function's return value follows the same
433   *   logic as $.each(). Returning true will continue to the next matched
434   *   element in the set, while returning false will entirely break the
435   *   iteration.
436   */
437  $.fn.removeOnce = function (id, fn) {
438    var name = id + '-processed';
439    var elements = this.filter('.' + name).removeClass(name);
440
441    return $.isFunction(fn) ? elements.each(fn) : elements;
442  };
443})(jQuery);
444;/*})'"*/;/*})'"*/
445var Drupal = Drupal || { 'settings': {}, 'behaviors': {}, 'locale': {} };
446
447// Allow other JavaScript libraries to use $.
448jQuery.noConflict();
449
450(function ($) {
451
452/**
453 * Override jQuery.fn.init to guard against XSS attacks.
454 *
455 * See http://bugs.jquery.com/ticket/9521
456 */
457var jquery_init = $.fn.init;
458$.fn.init = function (selector, context, rootjQuery) {
459  // If the string contains a "#" before a "<", treat it as invali
459d HTML.
460  if (selector && typeof selector === 'string') {
461    var hash_position = selector.indexOf('#');
462    if (hash_position >= 0) {
463      var bracket_position = selector.indexOf('<');
464      if (bracket_position > hash_position) {
465        throw 'Syntax error, unrecognized expression: ' + selector;
466      }
467    }
468  }
469  return jquery_init.call(this, selector, context, rootjQuery);
470};
471$.fn.init.prototype = jquery_init.prototype;
472
473/**
474 * Pre-filter Ajax requests to guard against XSS attacks.
475 *
476 * See https://github.com/jquery/jquery/issues/2432
477 */
478if ($.ajaxPrefilter) {
479  // For newer versions of jQuery, use an Ajax prefilter to prevent
480  // auto-executing script tags from untrusted domains. This is similar to the
481  // fix that is built in to jQuery 3.0 and higher.
482  $.ajaxPrefilter(function (s) {
483    if (s.crossDomain) {
484      s.contents.script = false;
485    }
486  });
487}
488else if ($.httpData) {
489  // For the version of jQuery that ships with Drupal core, override
490  // jQuery.httpData to prevent auto-detecting "script" data types from
491  // untrusted domains.
492  var jquery_httpData = $.httpData;
493  $.httpData = function (xhr, type, s) {
494    // @todo Consider backporting code from newer jQuery versions to check for
495    //   a cross-domain request here, rather than using Drupal.urlIsLocal() to
496    //   block scripts from all URLs that are not on the same site.
497    if (!type && !Drupal.urlIsLocal(s.url)) {
498      var content_type = xhr.getResponseHeader('content-type') || '';
499      if (content_type.indexOf('javascript') >= 0) {
500        // Default to a safe data type.
501        type = 'text';
502      }
503    }
504    return jquery_httpData.call(this, xhr, type, s);
505  };
506  $.httpData.prototype = jquery_httpData.prototype;
507}
508
509/**
510 * Attach all registered behaviors to a page element.
511 *
512 * Behaviors are event-triggered actions that attach to page elements, enhancing
513 * default non-JavaScript UIs. Behaviors are registered in the Drupal.behaviors
514 * object using the method 'attach' and optionally also 'detach' as follows:
515 * @code
516 *    Drupal.behaviors.behaviorName = {
517 *      attach: function (context, settings) {
518 *        ...
519 *      },
520 *      detach: function (context, settings, trigger) {
521 *        ...
522 *      }
523 *    };
524 * @endcode
525 *
526 * Drupal.attachBehaviors is added below to the jQuery ready event and so
527 * runs on initial page load. Developers implementing AHAH/Ajax in their
528 * solutions should also call this function after new page content has been
529 * loaded, feeding in an element to be processed, in order to attach all
530 * behaviors to the new content.
531 *
532 * Behaviors should use
533 * @code
534 *   $(selector).once('behavior-name', function () {
535 *     ...
536 *   });
537 * @endcode
538 * to ensure the behavior is attached only once to a given element. (Doing so
539 * enables the reprocessing of given elements, which may be needed on occasion
540 * despite the ability to limit behavior attachment to a particular element.)
541 *
542 * @param context
543 *   An element to attach behaviors to. If none is given, the document element
544 *   is used.
545 * @param settings
546 *   An object containing settings for the current context. If none given, the
547 *   global Drupal.settings object is used.
548 */
549Drupal.attachBehaviors = function (context, settings) {
550  context = context || document;
551  settings = settings || Drupal.settings;
552  // Execute all of them.
553  $.each(Drupal.behaviors, function () {
554    if ($.isFunction(this.attach)) {
555      this.attach(context, settings);
556    }
557  });
558};
559
560/**
561 * Detach registered behaviors from a page element.
562 *
563 * Developers implementing AHAH/Ajax in their solutions should call this
564 * function before page content is about to be removed, feeding in an element
565 * to be processed, in order to allow special behaviors to detach from the
566 * content.
567 *
568 * Such implementations should look for the class name that was added in their
569 * corresponding Drupal.behaviors.behaviorName.attach implementation, i.e.
570 * behaviorName-processed, to ensure the behavior is detached only from
571 * previously processed elements.
572 *
573 * @param context
574 *   An element to detach behaviors from. If none is given, the document element
575 *   is used.
576 * @param settings
577 *   An object containing settings for the current context. If none given, the
578 *   global Drupal.settings object is used.
579 * @param trigger
580 *   A string containing what's causing the behaviors to be detached. The
581 *   possible triggers are:
582 *   - unload: (default) The context element is being removed from the DOM.
583 *   - move: The element is about to be moved within the DOM (for example,
584 *     during a tabledrag row swap). After the move is completed,
585 *     Drupal.attachBehaviors() is called, so that the behavior can undo
586 *     whatever it did in response to the move. Many behaviors won't need to
587 *     do anything simply in response to the element being moved, but because
588 *     IFRAME elements reload their "src" when being moved within the DOM,
589 *     behaviors bound to IFRAME elements (like WYSIWYG editors) may need to
590 *     take some action.
591 *   - serialize: When an Ajax form is submitted, this is called with the
592 *     form as the context. This provides every behavior within the form an
593 *     opportunity to ensure that the field elements have correct content
594 *     in them before the form is serialized. The canonical use-case is so
595 *     that WYSIWYG editors can update the hidden textarea to which they are
596 *     bound.
597 *
598 * @see Drupal.attachBehaviors
599 */
600Drupal.detachBehaviors = function (context, settings, trigger) {
601  context = context || document;
602  settings = settings || Drupal.settings;
603  trigger = trigger || 'unload';
604  // Execute all of them.
605  $.each(Drupal.behaviors, function () {
606    if ($.isFunction(this.detach)) {
607      this.detach(context, settings, trigger);
608    }
609  });
610};
611
612/**
613 * Encode special characters in a plain-text string for display as HTML.
614 *
615 * @ingroup sanitization
616 */
617Drupal.checkPlain = function (str) {
618  var character, regex,
619      replace = { '&': '&amp;', "'": '&#39;', '"': '&quot;', '<': '&lt;', '>': '&gt;' };
620  str = String(str);
621  for (character in replace) {
622    if (replace.hasOwnProperty(character)) {
623      regex = new RegExp(character, 'g');
624      str = str.replace(regex, replace[character]);
625    }
626  }
627  return str;
628};
629
630/**
631 * Replace placeholders with sanitized values in a string.
632 *
633 * @param str
634 *   A string with placeholders.
635 * @param args
636 *   An object of replacements pairs to make. Incidences of any key in this
637 *   array are replaced with the corresponding value. Based on the first
638 *   character of the key, the value is escaped and/or themed:
639 *    - !variable: inserted as is
640 *    - @variable: escape plain text to HTML (Drupal.checkPlain)
641 *    - %variable: escape text and theme as a placeholder for user-submitted
642 *      content (checkPlain + Drupal.theme('placeholder'))
643 *
644 * @see Drupal.t()
645 * @ingroup sanitization
646 */
647Drupal.formatString = function(str, args) {
648  // Transform arguments before inserting them.
649  for (var key in args) {
650    if (args.hasOwnProperty(key)) {
651      switch (key.charAt(0)) {
652        // Escaped only.
653        case '@':
654          args[key] = Drupal.checkPlain(args[key]);
655          break;
656        // Pass-through.
657        case '!':
658          break;
659        // Escaped and placeholder.
660        default:
661          args[key] = Drupal.theme('placeholder', args[key]);
662          break;
663      }
664    }
665  }
666
667  return Drupal.stringReplace(str, args, null);
668};
669
670/**
671 * Replace substring.
672 *
673 * The longest keys will be tried first. Once a substring has been replaced,
674 * its new value will not be searched again.
675 *
676 * @param {String} str
677 *   A string with placeholders.
678 * @param {Object} args
679 *   Key-value pairs.
680 * @param {Array|null} keys
681 *   Array of keys from the "args".  Internal use only.
682 *
683 * @return {String}
684 *   Returns the replaced string.
685 */
686Drupal.stringReplace = function (str, args, keys) {
687  if (str.length === 0) {
688    return str;
689  }
690
691  // If the array of keys is not passed then collect the keys from the args.
692  if (!$.isArray(keys)) {
693    keys = [];
694    for (var k in args) {
695      if (args.hasOwnProperty(k)) {
696        keys.push(k);
697      }
698    }
699
700    // Order the keys by the character length. The shortest one is the first.
701    keys.sort(function (a, b) { return a.length - b.length; });
702  }
703
704  if (keys.length === 0) {
705    return str;
706  }
707
708  // Take next longest one from the end.
709  var key = keys.pop();
710  var fragments = str.split(key);
711
712  if (keys.length) {
713    for (var i = 0; i < fragments.length; i++) {
714      // Process each fragment with a copy of remaining keys.
715      fragments[i] = Drupal.stringReplace(fragments[i], args, keys.slice(0));
716    }
717  }
718
719  return fragments.join(args[key]);
720};
721
722/**
723 * Translate strings to the page language or a given language.
724 *
725 * See the documentation of the server-side t() function for further details.
726 *
727 * @param str
728 *   A string containing the English string to translate.
729 * @param args
730 *   An object of replacements pairs to make after translation. Incidences
731 *   of any key in this array are replaced with the corresponding value.
732 *   See Drupal.formatString().
733 *
734 * @param options
735 *   - 'context' (defaults to the empty context): The context the source string
736 *     belongs to.
737 *
738 * @return
739 *   The translated string.
740 */
741Drupal.t = function (str, args, options) {
742  options = options || {};
743  options.context = options.context || '';
744
745  // Fetch the localized version of the string.
746  if (Drupal.locale.strings && Drupal.locale.strings[options.context] && Drupal.locale.strings[options.context][str]) {
747    str = Drupal.locale.strings[options.context][str];
748  }
749
750  if (args) {
751    str = Drupal.formatString(str, args);
752  }
753  return str;
754};
755
756/**
757 * Format a string containing a count of items.
758 *
759 * This function ensures that the string is pluralized correctly. Since Drupal.t() is
760 * called by this function, make sure not to pass already-localized strings to it.
761 *
762 * See the documentation of the server-side format_plural() function for further details.
763 *
764 * @param count
765 *   The item count to display.
766 * @param singular
767 *   The string for the singular case. Please make sure it is clear this is
768 *   singular, to ease translation (e.g. use "1 new comment" instead of "1 new").
769 *   Do not use @count in the singular string.
770 * @param plural
771 *   The string for the plural case. Please make sure it is clear this is plural,
772 *   to ease translation. Use @count in place of the item count, as in "@count
773 *   new comments".
774 * @param args
775 *   An object of replacements pairs to make after translation. Incidences
776 *   of any key in this array are replaced with the corresponding value.
777 *   See Drupal.formatString().
778 *   Note that you do not need to include @count in this array.
779 *   This replacement is done automatically for the plural case.
780 * @param options
781 *   The options to pass to the Drupal.t() function.
782 * @return
783 *   A translated string.
784 */
785Drupal.formatPlural = function (count, singular, plural, args, options) {
786  args = args || {};
787  args['@count'] = count;
788  // Determine the index of the plural form.
789  var index = Drupal.locale.pluralFormula ? Drupal.locale.pluralFormula(args['@count']) : ((args['@count'] == 1) ? 0 : 1);
790
791  if (index == 0) {
792    return Drupal.t(singular, args, options);
793  }
794  else if (index == 1) {
795    return Drupal.t(plural, args, options);
796  }
797  else {
798    args['@count[' + index + ']'] = args['@count'];
799    delete args['@count'];
800    return Drupal.t(plural.replace('@count', '@count[' + index + ']'), args, options);
801  }
802};
803
804/**
805 * Returns the passed in URL as an absolute URL.
806 *
807 * @param url
808 *   The URL string to be normalized to an absolute URL.
809 *
810 * @return
811 *   The normalized, absolute URL.
812 *
813 * @see https://github.com/angular/angular.js/blob/v1.4.4/src/ng/urlUtils.js
814 * @see https://grack.com/blog/2009/11/17/absolutizing-url-in-javascript
815 * @see https://github.com/jquery/jquery-ui/blob/1.11.4/ui/tabs.js#L53
816 */
817Drupal.absoluteUrl = function (url) {
818  var urlParsingNode = document.createElement('a');
819
820  // Decode the URL first; this is required by IE <= 6. Decoding non-UTF-8
821  // strings may throw an exception.
822  try {
823    url = decodeURIComponent(url);
824  } catch (e) {}
825
826  urlParsingNode.setAttribute('href', url);
827
828  // IE <= 7 normalizes the URL when assigned to the anchor node similar to
829  // the other browsers.
830  return urlParsingNode.cloneNode(false).href;
831};
832
833/**
834 * Returns true if the URL is within Drupal's base path.
835 *
836 * @param url
837 *   The URL string to be tested.
838 *
839 * @return
840 *   Boolean true if local.
841 *
842 * @see https://github.com/jquery/jquery-ui/blob/1.11.4/ui/tabs.js#L58
843 */
844Drupal.urlIsLocal = function (url) {
845  // Always use browser-derived absolute URLs in the comparison, to avoid
846  // attempts to break out of the base path using directory traversal.
847  var absoluteUrl = Drupal.absoluteUrl(url);
848  var protocol = location.protocol;
849
850  // Consider URLs that match this site's base URL but use HTTPS instead of HTTP
851  // as local as well.
852  if (protocol === 'http:' && absoluteUrl.indexOf('https:') === 0) {
853    protocol = 'https:';
854  }
855  var baseUrl = protocol + '//' + location.host + Drupal.settings.basePath.slice(0, -1);
856
857  // Decoding non-UTF-8 strings may throw an exception.
858  try {
859    absoluteUrl = decodeURIComponent(absoluteUrl);
860  } catch (e) {}
861  try {
862    baseUrl = decodeURIComponent(baseUrl);
863  } catch (e) {}
864
865  // The given URL matches the site's base URL, or has a path under the site's
866  // base URL.
867  return absoluteUrl === baseUrl || absoluteUrl.indexOf(baseUrl + '/') === 0;
868};
869
870/**
871 * Sanitizes a URL for use with jQuery.ajax().
872 *
873 * @param url
874 *   The URL string to be sanitized.
875 *
876 * @return
877 *   The sanitized URL.
878 */
879Drupal.sanitizeAjaxUrl = function (url) {
880  var regex = /\=\?(&|$)/;
881  while (url.match(regex)) {
882    url = url.replace(regex, '');
883  }
884  return url;
885}
886
887/**
888 * Generate the themed representation of a Drupal object.
889 *
890 * All requests for themed output must go through this function. It examines
891 * the request and routes it to the appropriate theme function. If the current
892 * theme does not provide an override function, the generic theme function is
893 * called.
894 *
895 * For example, to retrieve the HTML for text that should be emphasized and
896 * displayed as a placeholder inside a sentence, call
897 * Drupal.theme('placeholder', text).
898 *
899 * @param func
900 *   The name of the theme function to call.
901 * @param ...
902 *   Additional arguments to pass along to the theme function.
903 * @return
904 *   Any data the theme function returns. This could be a plain HTML string,
905 *   but also a complex object.
906 */
907Drupal.theme = function (func) {
908  var args = Array.prototype.slice.apply(arguments, [1]);
909
910  return (Drupal.theme[func] || Drupal.theme.prototype[func]).apply(this, args);
911};
912
913/**
914 * Freeze the current body height (as minimum height). Used to prevent
915 * unnecessary upwards scrolling when doing DOM manipulations.
916 */
917Drupal.freezeHeight = function () {
918  Drupal.unfreezeHeight();
919  $('<div id="freeze-height"></div>').css({
920    position: 'absolute',
921    top: '0px',
922    left: '0px',
923    width: '1px',
924    height: $('body').css('height')
925  }).appendTo('body');
926};
927
928/**
929 * Unfreeze the body height.
930 */
931Drupal.unfreezeHeight = function () {
932  $('#freeze-height').remove();
933};
934
935/**
936 * Encodes a Drupal path for use in a URL.
937 *
938 * For aesthetic reasons slashes are not escaped.
939 */
940Drupal.encodePath = function (item, uri) {
941  uri = uri || location.href;
942  return encodeURIComponent(item).replace(/%2F/g, '/');
943};
944
945/**
946 * Get the text selection in a textarea.
947 */
948Drupal.getSelection = function (element) {
949  if (typeof element.selectionStart != 'number' && document.selection) {
950    // The current selection.
951    var range1 = document.selection.createRange();
952    var range2 = range1.duplicate();
953    // Select all text.
954    range2.moveToElementText(element);
955    // Now move 'dummy' end point to end point of original range.
956    range2.setEndPoint('EndToEnd', range1);
957    // Now we can calculate start and end points.
958    var start = range2.text.length - range1.text.length;
959    var end = start + range1.text.length;
960    return { 'start': start, 'end': end };
961  }
962  return { 'start': element.selectionStart, 'end': element.selectionEnd };
963};
964
965/**
966 * Add a global variable which determines if the window is being unloaded.
967 *
968 * This is primarily used by Drupal.displayAjaxError().
969 */
970Drupal.beforeUnloadCalled = false;
971$(window).bind('beforeunload pagehide', function () {
972    Drupal.beforeUnloadCalled = true;
973});
974
975/**
976 * Displays a JavaScript error from an Ajax response when appropriate to do so.
977 */
978Drupal.displayAjaxError = function (message) {
979  // Skip displaying the message if the user deliberately aborted (for example,
980  // by reloading the page or navigating to a different page) while the Ajax
981  // request was still ongoing. See, for example, the discussion at
982  // http://stackoverflow.com/questions/699941/handle-ajax-error-when-a-user-clicks-refresh.
983  if (!Drupal.beforeUnloadCalled) {
984    alert(message);
985  }
986};
987
988/**
989 * Build an error message from an Ajax response.
990 */
991Drupal.ajaxError = function (xmlhttp, uri, customMessage) {
992  var statusCode, statusText, pathText, responseText, readyStateText, message;
993  if (xmlhttp.status) {
994    statusCode = "\n" + Drupal.t("An AJAX HTTP error occurred.") +  "\n" + Drupal.t("HTTP Result Code: !status", {'!status': xmlhttp.status});
995  }
996  else {
997    statusCode = "\n" + Drupal.t("An AJAX HTTP request terminated abnormally.");
998  }
999  statusCode += "\n" + Drupal.t("Debugging information follows.");
1000  pathText = "\n" + Drupal.t("Path: !uri", {'!uri': uri} );
1001  statusText = '';
1002  // In some cases, when statusCode == 0, xmlhttp.statusText may not be defined.
1003  // Unfortunately, testing for it with typeof, etc, doesn't seem to catch that
1004  // and the test causes an exception. So we need to catch the exception here.
1005  try {
1006    statusText = "\n" + Drupal.t("StatusText: !statusText", {'!statusText': $.trim(xmlhttp.statusText)});
1007  }
1008  catch (e) {}
1009
1010  responseText = '';
1011  // Again, we don't have a way to know for sure whether accessing
1012  // xmlhttp.responseText is going to throw an exception. So we'll catch it.
1013  try {
1014    responseText = "\n" + Drupal.t("ResponseText: !responseText", {'!responseText': $.trim(xmlhttp.responseText) } );
1015  } catch (e) {}
1016
1017  // Make the responseText more readable by stripping HTML tags and newlines.
1018  responseText = responseText.replace(/<("[^"]*"|'[^']*'|[^'">])*>/gi,"");
1019  responseText = responseText.replace(/[\n]+\s+/g,"\n");
1020
1021  // We don't need readyState except for status == 0.
1022  readyStateText = xmlhttp.status == 0 ? ("\n" + Drupal.t("ReadyState: !readyState", {'!readyState': xmlhttp.readyState})) : "";
1023
1024  // Additional message beyond what the xmlhttp object provides.
1025  customMessage = customMessage ? ("\n" + Drupal.t("CustomMessage: !customMessage", {'!customMessage': customMessage})) : "";
1026
1027  message = statusCode + pathText + statusText + customMessage + responseText + readyStateText;
1028  return message;
1029};
1030
1031// Class indicating that JS is enabled; used for styling purpose.
1032$('html').addClass('js');
1033
1034$(function () {
1035  if (Drupal.settings.setHasJsCookie === 1) {
1036    // 'js enabled' cookie.
1037    document.cookie = 'has_js=1; path=/; SameSite=Lax';
1038  }
1039});
1040
1041/**
1042 * Additions to jQuery.support.
1043 */
1044$(function () {
1045  /**
1046   * Boolean indicating whether or not position:fixed is supported.
1047   */
1048  if (jQuery.support.positionFixed === undefined) {
1049    var el = $('<div style="position:fixed; top:10px" />').appendTo(document.body);
1050    jQuery.support.positionFixed = el[0].offsetTop === 10;
1051    el.remove();
1052  }
1053});
1054
1055//Attach all behaviors.
1056$(function () {
1057  Drupal.attachBehaviors(document, Drupal.settings);
1058});
1059
1060/**
1061 * The default themes.
1062 */
1063Drupal.theme.prototype = {
1064
1065  /**
1066   * Formats text for emphasized display in a placeholder inside a sentence.
1067   *
1068   * @param str
1069   *   The text to format (plain-text).
1070   * @return
1071   *   The formatted text (html).
1072   */
1073  placeholder: function (str) {
1074    return '<em class="placeholder">' + Drupal.checkPlain(str) + '</em>';
1075  }
1076};
1077
1078})(jQuery);
1079;/*})'"*/;/*})'"*/
1080/**
1081 * Workaround for deprecated $.browser which was removed in jQuery 1.9
1082 * @see https://api.jquery.com/jquery.browser/
1083 */
1084(function ($) {
1085  if ($.browser===undefined) {
1086    $.browser={};
1087    $.browser.msie=false;
1088    $.browser.version=0;
1089    if (navigator.userAgent.match(/MSIE ([0-9]+)\./)) {
1090      $.browser.msie=true;
1091      $.browser.version=RegExp.$1;
1092    }
1093  }
1094})(jQuery);
1095;/*})'"*/;/*})'"*/

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.