PageSourceSearch

https://www.myallsearch.com/site/themes/default/assets/js/app.js?v=1.0

js myallsearch.com collected 2026-10-03 20:45:48 UTC 49,262 bytes, 1,570 lines download raw bytes

1"use strict";
2
3function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
4
5function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
6
7function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
8
9function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
10
11function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); }
12
13function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
14
15function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
16
17function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
18
19var $loader = $('#ajax-loader');
20var $loaderInfinite = $('#ajax-loader-infinite');
21var xhr;
22var notyfOpts = {
23  types: [{
24    type: 'success',
25    backgroundColor: 'auto',
26    className: 'notyf-success',
27    icon: false
28  }, {
29    type: 'danger',
30    backgroundColor: 'auto',
31    className: 'notyf-danger',
32    icon: false
33  }, {
34    type: 'error',
35    backgroundColor: 'auto',
36    className: 'notyf-danger',
37    icon: false
38  }, {
39    type: 'info',
40    className: 'notyf-info',
41    icon: false
42  }, {
43    type: 'warning',
44    className: 'notyf-warning',
45    icon: false
46  }, {
47    type: 'snack',
48    className: 'notyf-snack',
49    icon: false
50  }],
51  position: {
52    x: 'center',
53    y: 'bottom'
54  },
55  duration: 2500,
56  ripple: true
57};
58window.notyf = new Notyf(notyfOpts);
59var datePickerOpts = {
60  selectMonths: false,
61  formatSubmit: 'dd/mmmm/yyyy'
62};
63var recaptchaLoaded = false;
64
65if (typeof grecaptcha !== 'undefined') {
66  recaptchaLoaded = true;
67}
68
69var recaptchaWidgets = {};
70
71if (window.Parsley) {
72  window.Parsley.addValidator('maxFileSize', {
73    validateString: function validateString(_value, maxSize, parsleyInstance) {
74      var files = parsleyInstance.$element[0].files;
75      return files.length != 1 || files[0].size <= maxSize * 1024;
76    },
77    requirementType: 'integer',
78    messages: {
79      custom: window.locale["validation-max-file-size"]
80    }
81  });
82}
83/**
84 * Callback for recaptcha
85 *
86 * @param   token
87 */
88
89
90function recaptchaSuccessCallback(token) {
91  $('.captcha-error').each(function (index, el) {
92    $(this).hide();
93  });
94  $('.recaptcha-error').each(function (index, el) {
95    $(this).removeClass('recaptcha-error');
96  });
97}
98/**
99 * The theme object
100 *
101 * @type {Object}
102 */
103
104
105var $theme = {};
106/**
107 * Options for parsley
108 *
109 * @type {Object}
110 */
111
112$theme.parsleyOptions = {
113  errorClass: 'is-invalid',
114  successClass: 'is-valid',
115  errorsWrapper: '<span class="parsley-text form-text text-danger"></span>',
116  errorTemplate: '<span></span>',
117  trigger: 'focusout',
118  focusInvalid: true,
119  errorsContainer: function errorsContainer(el) {
120    return el.$element.closest('.form-group');
121  }
122};
123/**
124 * Get svg icon for an ID
125 *
126 * @param  {String} id
127 * @param  {String} classes
128 * @param  {Object} attrs
129 * @return {String}
130 */
131
132$theme.svgIcon = function (id, classes, attrs) {
133  attrs = attrs || {};
134  classes = classes || '';
135  classes = 'svg-icon ' + classes;
136  var attrText = '';
137
138  for (prop in attrs) {
139    if (prop == 'class') {
140      continue;
141    }
142
143    attrText += '' + prop + '="' + attrs[prop] + '"';
144  }
145
146  return '<svg class="' + classes + '" ' + attrText + '><use xlink:href="#' + id + '"/></svg>';
147};
148/**
149 * Get svg icon for alert type
150 *
151 * @param  {String} type
152 * @return {String}
153 */
154
155
156$theme.svgIconForAlert = function (type) {
157  var svgID = 'notifications';
158
159  switch (type) {
160    case 'danger':
161    case 'warning':
162      svgID = 'warning';
163      break;
164
165    case 'success':
166      svgID = 'checkmark';
167      break;
168
169    default:
170      svgID = 'notifications';
171      break;
172  }
173
174  return $theme.svgIcon(svgID);
175};
176/**
177* Builds a bootstrap alert
178*
179* @param  String text
180* @param  String type
181* @param  Boolean dismissable
182* @return String
183*/
184
185
186$theme.buildAlert = function (text, type, dismissable, withIcon) {
187  type = type || 'success';
188  var icon_class = ' ';
189
190  if (withIcon) {
191    icon_class = ' alert-icon ';
192  }
193
194  var html = '<div class="alert' + icon_class + 'alert-' + type + '">';
195
196  if (withIcon) {
197    html += $theme.svgIconForAlert(type, 'mr-2');
198  }
199
200  if (dismissable) {
201    html += '<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">&times;</span></button>';
202  }
203
204  html += text + '</div>';
205  return html;
206};
207/**
208 * Localize numbers
209 *
210 * @param  {String} text
211 * @return {String}
212 */
213
214
215$theme.localizeNumbers = function (text) {
216  text = text.toString();
217
218  for (var counter = 0; counter < 10; counter++) {
219    var key = "num_" + counter;
220    text = text.replace(new RegExp(counter, 'g'), window.locale[key]);
221  }
222
223  return text;
224};
225/**
226 * Function to update a URL parameter
227 *
228 * @param  {String} uri
229 * @param  {String} paramKey
230 * @param  {String} paramVal
231 * @return {String}
232 */
233
234
235$theme.updateUrlParam = function (uri, paramKey, paramVal) {
236  var url = new URL(uri);
237  var search_params = url.searchParams;
238  search_params.set(paramKey, paramVal);
239  url.search = search_params.toString();
240  return url.toString();
241};
242/**
243 * String templating
244 *
245 * @param  {String} text
246 * @param  {Object} replacements
247 * @return {String}
248 */
249
250
251$theme.strtpl = function (text, replacements) {
252  text = text.replace(/\%(\s*?[\w.]+\s*?)%/mg, function (match, contents, offset, input_string) {
253    if (contents in replacements) {
254      return replacements[contents];
255    }
256
257    console.log('No replacement found for ' + match);
258    return '';
259  });
260  return text;
261};
262/**
263 * Build query string from object
264 *
265 * @param  {Object} obj
266 * @return {String}
267 */
268
269
270$theme.buildQueryString = function (obj) {
271  var str = [];
272
273  for (var p in obj) {
274    if (obj.hasOwnProperty(p)) {
275      str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
276    }
277  }
278
279  return str.join("&");
280};
281/**
282 * Perform a redirect
283 *
284 * @param  {String} url
285 * @param  {Boolean} cache
286 * @param  {Boolean} httpRedirect
287 */
288
289
290$theme.redirect = function (url, cache, httpRedirect) {
291  if (cache === false) {
292    var time = new Date().getTime();
293    url = $theme.updateUrlParam(url, '_', time);
294  }
295
296  if (httpRedirect) {
297    window.location.replace(url);
298  } else {
299    window.location.href = url;
300  }
301
302  return true;
303};
304/**
305 * Alias of $theme.redirect() for quick HTTP redirection
306 *
307 * @param  {String} url
308 * @param  {Boolean} cache
309 */
310
311
312$theme.httpRedirect = function (url, cache) {
313  return $theme.redirect(url, cache, true);
314};
315/**
316 * Alias of $theme.redirect() for current page reloading
317 *
318 * @param  {Boolean} httpRedirect
319 * @param  {Boolean} cache
320 */
321
322
323$theme.selfReload = function (httpRedirect, cache) {
324  httpRedirect = httpRedirect || false;
325  cache = cache || true;
326  return $theme.redirect(window.location.href, cache, httpRedirect);
327};
328
329$theme.isObject = function (value) {
330  return value && _typeof(value) === 'object' && value.constructor === Object;
331};
332
333$theme.isString = function (value) {
334  return typeof value === 'string' || value instanceof String;
335};
336
337$theme.scrollToID = function (id, offset, delay) {
338  offset = offset || 70;
339  delay = delay || 500;
340
341  if (!id.startsWith('#')) {
342    id = '#' + id;
343  }
344
345  var position = $(id).offset().top - offset;
346  $('html, body').animate({
347    scrollTop: position
348  }, delay);
349};
350/**
351 * Initilazes parley with the options
352 *
353 */
354
355
356$theme.loadParsley = function () {
357  if (window.Parsley) {
358    $("form").parsley($theme.parsleyOptions);
359    window.Parsley.on('field:error', function (el) {
360      this.$element.closest('.form-group').removeClass('input-has-success').addClass('input-has-error');
361    });
362    window.Parsley.on('field:success', function (el) {
363      this.$element.closest('.form-group').removeClass('input-has-error').addClass('input-has-success');
364    });
365  }
366};
367/**
368 * Refreshes Google Recaptcha
369 *
370 */
371
372
373$theme.refreshRecaptcha = function () {
374  if (!recaptchaLoaded) {
375    return;
376  }
377
378  $('.g-recaptcha').each(function (index, el) {
379    var captcha = $(this);
380    var id = captcha.attr('id');
381    var options = {
382      sitekey: window.app.recaptchaSiteKey
383    };
384    var dataAttrs = ['sitekey', 'theme', 'tabindex', 'callback', 'expired-callback', 'error-callback'];
385    var val = '';
386
387    for (var i = dataAttrs.length - 1; i >= 0; i--) {
388      val = dataAttrs[i];
389      var value = captcha.data(val);
390
391      if (value) {
392        options[val] = value;
393      }
394    } // Google throws error when rendering twice
395
396
397    try {
398      var widgetId = grecaptcha.render(el, options);
399      recaptchaWidgets[id] = widgetId;
400    } catch (e) {}
401  });
402};
403/**
404 * Reload the markup after DOM changes
405 *
406 * @param  {String} target
407 */
408
409
410$theme.refreshMarkup = function (target) {
411  $theme.loadParsley();
412  $theme.refreshRecaptcha();
413  $('.navdrawer-backdrop').remove();
414  dynamicThemeEvents();
415  $('.floating-label .custom-select, .floating-label .form-control').floatinglabel();
416};
417/**
418 * Starts the ajaxLoader
419 *
420 * @param  {Boolean} insideForm Determines if the request is sent from a form submit or not
421 */
422
423
424$theme.startLoader = function (insideForm) {
425  $loader.width(0).show();
426
427  if (insideForm) {
428    return;
429  }
430
431  $loader.width(30 + Math.random() * 30 + "%");
432};
433/**
434 * Finish the ajaxLoader
435 *
436 * @param  {Boolean} insideForm Determines if the request is sent from a form submit or not
437 */
438
439
440$theme.finishLoader = function () {
441  $loader.width("100%").delay(50).fadeOut(400, function () {
442    $(this).width("0");
443  });
444};
445
446$theme.showInfiniteLoader = function () {
447  $loaderInfinite.width("100%").fadeIn('fast');
448};
449
450$theme.hideInfiniteLoader = function () {
451  $loaderInfinite.width("0").fadeOut('fast');
452};
453/**
454 * Call a function
455 *
456 * @param  {String} funcname
457 * @param  {Array} args
458 */
459
460
461$theme.callFunction = function (funcname, args) {
462  if (!funcname) {
463    return;
464  }
465
466  if (typeof funcname === "function") {
467    return funcname.apply(null, args);
468  }
469
470  return window[funcname].apply(null, args);
471};
472/**
473 * Handles Pjax loading
474 *
475 * @param  {String} target
476 * @param  {String} type
477 * @param  {Object} params
478 * @param  {Object} options
479 */
480
481
482$theme.ajaxContentLoad = function (target, type, params, options) {
483  var formattedTarget;
484  type = type || 'get';
485  params = params || {};
486  options = options || {};
487
488  if (!options.el) {
489    options.el = null;
490  }
491
492  if (type.toLowerCase() == 'post') {
493    type = 'POST';
494    params[app.csrfKey] = app.csrfToken;
495  } else {
496    type = 'GET';
497  }
498
499  if (options.instantFetch) {
500    formattedTarget = target;
501  } else {
502    formattedTarget = $theme.updateUrlParam(target, 'ajax', 'true');
503  }
504
505  var finished = $theme.callFunction(options.pre_callback, [options.el]); // if explicitly returned TRUE we assume callback wants to handle the response completely on it's own
506
507  if (finished === true) {
508    return;
509  }
510
511  $theme.startLoader();
512  $.ajax({
513    url: formattedTarget,
514    data: params,
515    type: type,
516    xhr: function xhr() {
517      var xhr = $.ajaxSettings.xhr();
518
519      xhr.onprogress = function (e) {
520        if (e.lengthComputable) {
521          $loader.width(e.loaded / e.total * 100 + '%');
522        }
523      };
524
525      xhr.upload.onprogress = function (e) {
526        if (e.lengthComputable) {
527          $loader.width(e.loaded / e.total * 100 + '%');
528        }
529      };
530
531      return xhr;
532    },
533    headers: {
534      'x-spark-ajax': true
535    }
536  }).done(function (response) {
537    $('body').removeClass('ajax-started');
538    var finished = $theme.callFunction(options.success_callback, [response, options.el]); // if explicitly returned TRUE we assume callback wants to handle the response completely on it's own
539
540    if (finished === true) {
541      return;
542    }
543
544    if (response.redirect) {
545      return $theme.redirect(response.redirect);
546    }
547
548    if (response.dash) {
549      $theme.ajaxContentLoad(response.dash, 'GET', {});
550      return;
551    }
552
553    if (response.title) {
554      document.title = response.title;
555    }
556
557    if (response.body_class) {
558      $('body').attr('class', response.body_class);
559    }
560
561    if (response.html_class) {
562      $('html').attr('class', response.html_class);
563    } // content that needs to be replaced
564
565
566    if (response.sections) {
567      for (var element in response.sections) {
568        $('#' + element).html(response.sections[element]);
569      }
570    } // content that needs to be appended
571
572
573    if (response.append) {
574      for (var element in response.append) {
575        $('#' + element).append(response.append[element]);
576      }
577    } // content that needs to be prepended
578
579
580    if (response.prepend) {
581      for (var element in response.prepend) {
582        $('#' + element).append(response.prepend[element]);
583      }
584    }
585
586    if (response.attr) {
587      for (var selector in response.attr) {
588        var attributes = response.attr[selector];
589
590        if (selector == 'this') {
591          options.el.attr(attributes);
592          continue;
593        }
594
595        for (var attr in attributes) {
596          var value = attributes[attr];
597          $(selector).each(function () {
598            $(this).attr(attr, value);
599          });
600        }
601      }
602    } // reload the plugins
603
604
605    $theme.refreshMarkup(target); // the request type is GET
606
607    if (type == 'GET') {
608      // If we are on a different URL then add set the pushstate
609      if (!options.instantFetch && target != window.location.href) {
610        if (response.url) {
611          window.history.pushState({
612            path: response.url
613          }, '', response.url);
614        } else {
615          window.history.pushState({
616            path: target
617          }, '', target);
618        }
619      } // Update the route URL variable if provided
620
621
622      if (response.current_route_uri && window.app.currentRouteURI) {
623        window.app.currentRouteURI = response.current_route_uri;
624      } // Update the route name variable if provided
625
626
627      if (response.current_route_name && window.app.currentRouteName) {
628        window.app.currentRouteName = response.current_route_name;
629      }
630    } // optional scroll to top
631
632
633    if (options.scrolltop) {
634      $(document).scrollTop(0);
635    }
636  }).fail(function (response) {
637    var finished = $theme.callFunction(options.error_callback, [response, options.el]); // if explicitly returned TRUE we assume callback wants to handle the response completely on it's own
638
639    if (finished === true) {
640      return;
641    }
642
643    notyf.error(response.status + ' ' + response.statusText);
644  }).always(function () {
645    $theme.finishLoader();
646  });
647  $theme.callFunction(options.post_callback, [options.el]);
648};
649/**
650 * Handles ajax form submit
651 *
652 * @param  {Object} form The jQuery form element
653 * @return {[type]}
654 */
655
656
657$theme.ajaxFormHandler = function (form) {
658  var data = new FormData(form[0]);
659  var action = form.prop('action');
660  var method = form.prop('method').toLowerCase();
661  var parameters = '';
662  var reset = false;
663
664  if (form.data('reset') == true) {
665    reset = true;
666  }
667
668  if (method == 'get') {
669    method = 'GET';
670    parameters = _toConsumableArray(data.entries()).map(function (e) {
671      return encodeURIComponent(e[0]) + "=" + encodeURIComponent(e[1]);
672    });
673    parameters.push('ajax=true');
674    parameters = parameters.join('&');
675
676    if (parameters.length) {
677      action += '?' + parameters;
678    }
679  } else {
680    method = 'POST';
681  }
682
683  var success_callback = form.data('success-callback');
684  var error_callback = form.data('error-callback');
685  var redirect_to = form.data('data-redirect');
686  var recaptcha_id = form.data('recaptcha-id');
687  var notyf_position = form.data('toast-position');
688  var recaptcha_el = $('#' + recaptcha_id); // Recaptcha validation
689
690  if (recaptcha_el.length && recaptchaLoaded) {
691    var recaptcha_widget_id = recaptchaWidgets[recaptcha_id];
692
693    if (grecaptcha.getResponse(recaptcha_widget_id) == '') {
694      recaptcha_el.addClass('recaptcha-error');
695      $theme.scrollToID(recaptcha_id);
696      notyf.error(locale["invalid-captcha"]);
697      return;
698    }
699  }
700
701  var submit = form.find(':submit');
702  $theme.showInfiniteLoader(true);
703  submit.attr('disabled', true);
704  submit.addClass('btn-loading');
705  $.ajax({
706    url: action,
707    type: method,
708    processData: false,
709    contentType: false,
710    data: data,
711    async: true
712  }).done(function (response) {
713    var finished = $theme.callFunction(success_callback, [response, form]); // if explicitly returned TRUE we assume callback wants to handle the response completely on it's own
714
715    if (finished === true) {
716      return;
717    }
718
719    if (response.type) {
720      var type = response.type;
721      var duration = notyfOpts.duration; // Increase the time for longer texts
722
723      if (response.message.length > 100) {
724        duration = 4000;
725      }
726
727      var toast = {
728        type: type,
729        message: response.message,
730        duration: duration
731      };
732
733      if ($theme.isObject(notyf_position)) {
734        toast.position = notyf_position;
735      }
736      notyf.open(toast);
737    }
738
739    if (response.redirect) {
740      return $theme.httpRedirect(response.redirect);
741    }
742
743    if (response.dash) {
744      $theme.ajaxContentLoad(response.dash, 'GET', {});
745      return;
746    }
747
748    if (response.title) {
749      document.title = response.title;
750    }
751
752    if (response.body_class) {
753      $('body').attr('class', response.body_class);
754    }
755
756    if (recaptchaLoaded && recaptcha_el.length) {
757      grecaptcha.reset();
758    }
759
760    if (form.parsley && response.type && response.type == 'success') {
761      form.find('.input-has-success, .input-has-error').each(function (index, el) {
762        $(this).removeClass('input-has-success').removeClass('input-has-error');
763      });
764      form.parsley().reset();
765    }
766
767    if (reset && response.type && response.type == 'success') {
768      form.trigger('reset');
769      form.find('.custom-file-label').text(window.locale["choose-file"]);
770    }
771
772    if (response.url && response.form_change_url) {
773      window.history.pushState({
774        path: response.url
775      }, '', response.url);
776    } // content that needs to be replaced
777
778
779    if (response.sections) {
780      for (var element in response.sections) {
781        $('#' + element).html(response.sections[element]);
782      }
783    } // content that needs to be appended
784
785
786    if (response.append) {
787      for (var element in response.append) {
788        $('#' + element).append(response.append[element]);
789      }
790    } // content that needs to be prepended
791
792
793    if (response.prepend) {
794      for (var element in response.prepend) {
795        $('#' + element).append(response.prepend[element]);
796      }
797    }
798
799    if (response.attr) {
800      for (var selector in response.attr) {
801        var element = response.attr[selector];
802
803        for (var attr in element) {
804          var value = element[attr];
805          $(selector).each(function () {
806            $(this).attr(attr, value);
807          });
808        }
809      }
810    }
811
812    $theme.refreshMarkup();
813  }).fail(function (response) {
814    var finished = $theme.callFunction(error_callback, [response, form]); // if explicitly returned TRUE we assume callback wants to handle the response completely on it's own
815
816    if (finished === true) {
817      return;
818    }
819
820    notyf.error(response.status + ' ' + response.statusText);
821  }).always(function (response) {
822    $theme.hideInfiniteLoader();
823    submit.removeClass('btn-loading');
824    submit.attr('disabled', false);
825  });
826};
827/**
828 * Format AJAX response for form submission
829 *
830 * @param  {Mixed} response
831 * @return {String}
832 */
833
834
835$theme.formatAjaxResponse = function (response) {
836  if ($theme.isString(response)) {
837    return response;
838  }
839
840  if (!response.message) {
841    return false;
842  }
843
844  var dismissable = false;
845
846  if (response.dismissable) {
847    dismissable = true;
848  }
849
850  return $theme.buildAlert(response.message, response.type, dismissable, window.app.alertIcons);
851};
852
853$theme.escapeHTML = function (text) {
854  var map = {
855    '&': '&amp;',
856    '<': '&lt;',
857    '>': '&gt;',
858    '"': '&quot;',
859    "'": '&#039;'
860  };
861  return text.replace(/[&<>"']/g, function (m) {
862    return map[m];
863  });
864};
865
866var eye_svg_icon = $theme.svgIcon('eye');
867var eye_svg_icon_off = $theme.svgIcon('eye-off');
868/**
869 * Recaptcha callback
870 *
871 */
872
873function refreshRecaptcha() {
874  $theme.refreshRecaptcha();
875} // Load parsley because it doesn't work inside document ready
876
877
878$theme.loadParsley();
879$(document).ready(function () {
880  // Instant Fetch
881  if (window.app.enableAjaxNavigation) {
882    $(document).on('click', "a.sp-link", function (e) {
883      var link = $(this); // Ignore links that wants to open in a new window
884
885      if (link.attr('target') == '_blank') {
886        return;
887      }
888
889      var target = link.attr('href'); // No need for identifers or javascript urls
890
891      if (target.startsWith('#') == true || target.startsWith('javascript:')) {
892        return;
893      }
894
895      var abs_target = link.prop('href');
896      var target_host = new URL(abs_target).hostname;
897
898      if (target_host != window.location.hostname) {
899        return;
900      }
901
902      var method = link.data('method') || 'get';
903
904      if (method.toLowerCase() == 'post') {
905        method = 'post';
906      }
907
908      var parameters = {};
909      var params = link.data('params');
910
911      if ($theme.isObject(params)) {
912        parameters = params;
913      }
914
915      e.preventDefault();
916      var scrolltop = true;
917
918      if (link.data('scrolltop') === false) {
919        scrolltop = false;
920      }
921
922      var options = {
923        pre_callback: link.data('pre-callback'),
924        success_callback: link.data('success-callback'),
925        error_callback: link.data('error-callback'),
926        post_callback: link.data('post-callback'),
927        scrolltop: scrolltop,
928        el: link
929      };
930      $('body').addClass('ajax-started');
931      $theme.ajaxContentLoad(abs_target, method, parameters, options);
932    });
933  } // Dynamic components for custom content replacement
934
935
936  $(document).on('click', "[data-instant-ajax]", function (e) {
937    e.preventDefault();
938    var link = $(this);
939    var target = link.attr('data-instant-ajax');
940    var abs_target = target;
941    var method = link.data('method') || 'get';
942
943    if (method.toLowerCase() == 'post') {
944      method = 'post';
945    }
946
947    var parameters = {};
948    var params = link.data('params');
949
950    if ($theme.isObject(params)) {
951      parameters = params;
952    }
953
954    var options = {
955      pre_callback: link.data('pre-callback'),
956      success_callback: link.data('success-callback'),
957      error_callback: link.data('error-callback'),
958      post_callback: link.data('post-callback'),
959      scrolltop: false,
960      instantFetch: true,
961      el: link
962    };
963    $theme.ajaxContentLoad(abs_target, method, parameters, options);
964  }); // Handle back button press
965
966  if (window.app.enableAjaxNavigation) {
967    $(window).on('popstate', function (e) {
968      if (location.href.includes('#')) {
969        return false;
970      } // In case we were on a page where the content doesn't exist
971
972
973      if ($('#content').length) {
974        $theme.ajaxContentLoad(location.href, 'GET', {});
975      } else {
976        $theme.httpRedirect(location.href);
977      }
978    });
979  }
980
981  if (window.app.enableAjaxNavigation) {
982    $(document).on('submit', 'form[data-ajax-form]', function (e) {
983      var form = $(this);
984      var before_callback = form.data('before-callback');
985      var finished = $theme.callFunction(before_callback, [e]);
986
987      if (finished === true) {
988        return;
989      }
990
991      e.preventDefault();
992      $theme.ajaxFormHandler(form);
993    });
994  } // Custom file inputs
995
996
997  $(document).on('change', '.custom-file-input', function (e) {
998    var $el = $(this),
999        files = $el[0].files;
1000    var label_el = $el.next('.custom-file-label');
1001
1002    if (files.length < 1) {
1003      label_el.html(window.locale["choose-file"]);
1004      return;
1005    }
1006
1007    var label = files[0].name;
1008
1009    if (files.length > 1) {
1010      label = label + " and " + String(files.length - 1) + " more files";
1011    }
1012
1013    label_el.html(label);
1014  }); // Simple attribute based toggling
1015
1016  $(document).on('click', '[data-toggle="class"]', function (event) {
1017    event.preventDefault();
1018    var target = $(this).data('target');
1019    var targetEl;
1020
1021    if (!target) {
1022      targetEl = $(this);
1023    } else if (target == 'parent') {
1024      targetEl = $(this).parent();
1025    } else {
1026      targetEl = $(target);
1027    }
1028
1029    var classes = $(this).data('classes');
1030    targetEl.toggleClass(classes);
1031    return false;
1032  });
1033  $(document).on('click', '[data-focus]', function (event) {
1034    event.preventDefault();
1035    var target = $($(this).data('focus'));
1036    target.focus();
1037  });
1038}); // Executed on DOM load and also when the dom is loaded via ajax
1039
1040
1041let searchSuggetions = [];
1042
1043function dynamicThemeEvents() {
1044  // Start floating labels
1045  $('.floating-label .custom-select, .floating-label .form-control').floatinglabel();
1046  var body = $('body');
1047
1048  if (window.app.settings.search_autocomplete) {
1049    $('[data-autocomplete]').autocomplete({
1050      autosuggest: false,
1051      appendMethod: 'replace',
1052      openOnFocus: true,
1053      closeOnBlur: true,
1054      minLength: 3,
1055      accents: false,
1056      valid: function valid(value, query) {
1057        return true;
1058      },
1059      source: [function (q, add) {
1060        if (q.toString().length < 2) {
1061          return;
1062        }
1063
1064        $.ajax({
1065          url: 'https://suggestqueries.google.com/complete/search?json&client=firefox&hl=en&lr=en&ds=n&num=20&q=' + encodeURIComponent(q),
1066          jsonp: "callback",
1067          dataType: "jsonp",
1068          success: function success(response) {
1069            var suggestions = response[1]; // Remove the query itself
1070
1071            var index = suggestions.indexOf(q);
1072
1073            if (index !== -1) {
1074              suggestions.splice(index, 1);
1075            }
1076            searchSuggetions = suggestions;
1077            add(suggestions);
1078          }
1079        });
1080      }]
1081    }).on("open.xdsoft", function () {
1082      $(this).closest('.searchbox-group').addClass('suggestions-active');
1083    }).on("close.xdsoft", function () {
1084      $(this).closest('.searchbox-group').removeClass('suggestions-active');
1085    }).on('selected.xdsoft', function (e, data) {
1086      $("#searchForm").submit();
1087    });
1088    $(['data-autocomplete']).autocomplete('update');
1089  }
1090}
1091
1092function getParameterByName(name, url) {
1093  name = name.replace(/[\[\]]/g, '\\$&');
1094  var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
1095      results = regex.exec(url);
1096  if (!results) return null;
1097  if (!results[2]) return '';
1098  var val = decodeURIComponent(results[2].replace(/\+/g, ' '));
1099  return htmlEntities(val);
1100}
1101
1102function htmlEntities(str) {
1103  return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
1104}
1105
1106function preventEmptySubmit(e) {
1107  if (!$('input[name=q]').val().length) {
1108    e.preventDefault();
1109    return true;
1110  }
1111
1112  return false;
1113}
1114
1115var accordsMarkup = '<div class="card my-4"><div class="card-body py-2"><div class="list-group bg-transparent list-group-flush" id="answers-accordion"><h3 class="card-title m-0">People also search for:</h3></div></div>';
1116var accords = '';
1117var hasAccord = false;
1118jQuery(document).ready(function ($) {
1119  $('body').tooltip({
1120    selector: '[data-toggle="tooltip"], [data-tooltip]',
1121    boundary: 'window'
1122  });
1123  $(document).on('click', '.gs-spelling a', function (e) {
1124    var query = $(this).text();
1125    $('input[data-search-input]').val(query);
1126  });
1127  $(document).on('focus', '#home-search-input', function (e) {
1128    $('#dimmer').addClass('dimmer-active');
1129  });
1130  $(document).on('click', function (event) {
1131    var $trigger = $("#home-search-group");
1132
1133    if ($trigger !== event.target && !$trigger.has(event.target).length) {
1134      $('#dimmer').removeClass('dimmer-active');
1135    }
1136  });
1137  $(document).on('click', '.gs-previewLink', function (e) {
1138    var src = $(this).find('img').attr('src');
1139
1140    if (src) {
1141      e.preventDefault();
1142      window.open(src, '_blank');
1143    }
1144  });
1145
1146  if (!document.getElementById('myallsearch-search-nav-theme')) {
1147    $('<style id="myallsearch-search-nav-theme">' +
1148      '.gsc-webResult.gsc-result:has(.web-result) { margin-bottom:0 !important; padding-bottom:0 !important; }' +
1149      '.gsc-webResult.gsc-result:has(.web-result) .gs-webResult.gs-result { margin-bottom:0 !important; padding-bottom:0 !important; }' +
1150      '.find-elsewhere-button:hover, .myallsearch-page-nav:hover {' +
1151        'background:#f1f1f1 !important;' +
1152        'border-color:#dedede !important;' +
1153        'color:#333 !important;' +
1154      '}' +
1155      'body.dark-mode .find-elsewhere-button, body.dark-mode .myallsearch-page-nav,' +
1156      'html.dark-mode .find-elsewhere-button, html.dark-mode .myallsearch-page-nav,' +
1157      'body.theme-dark .find-elsewhere-button, body.theme-dark .myallsearch-page-nav {' +
1158        'background:#2b2b2b !important;' +
1159        'color:#d7d7d7 !important;' +
1160        'border-color:#505050 !important;' +
1161      '}' +
1162      '.find-elsewhere-button { position:relative; }' +
1163      '.find-elsewhere-privacy-warning {' +
1164        'display:none;position:absolute;
1164left:50%;bottom:calc(100% + 10px);transform:translateX(-50%);' +
1165        'width:230px;padding:10px 12px;border:1px solid #e1e4e8;border-radius:8px;' +
1166        'background:#fff;color:#4f5358;box-shadow:0 4px 14px rgba(0,0,0,.12);' +
1167        'font-size:12px;font-weight:400;line-height:1.4;text-align:left;white-space:normal;z-index:9999;' +
1168      '}' +
1169      '.find-elsewhere-button:hover .find-elsewhere-privacy-warning, .find-elsewhere-button:focus .find-elsewhere-privacy-warning {display:block;}' +
1170      'body.dark-mode .find-elsewhere-privacy-warning, html.dark-mode .find-elsewhere-privacy-warning, body.theme-dark .find-elsewhere-privacy-warning {' +
1171        'background:#2b2b2b;color:#d7d7d7;border-color:#505050;box-shadow:0 4px 14px rgba(0,0,0,.35);' +
1172      '}' +
1173      'body.dark-mode .find-elsewhere-button:hover, body.dark-mode .myallsearch-page-nav:hover,' +
1174      'html.dark-mode .find-elsewhere-button:hover, html.dark-mode .myallsearch-page-nav:hover,' +
1175      'body.theme-dark .find-elsewhere-button:hover, body.theme-dark .myallsearch-page-nav:hover {' +
1176        'background:#353535 !important;' +
1177        'border-color:#666 !important;' +
1178      '}' +
1179    '</style>').appendTo('head');
1180  }
1181
1182  // Allow long DuckDuckGo summary/fact values to wrap instead of being clipped.
1183  if (!document.getElementById('myallsearch-instant-answer-wrap-fix')) {
1184    $('<style id="myallsearch-instant-answer-wrap-fix">' +
1185      '#instant-answer, #instant-answer * {' +
1186        'overflow-wrap:anywhere;' +
1187        'word-break:normal;' +
1188      '}' +
1189      '#instant-answer .text-truncate {' +
1190        'white-space:normal !important;' +
1191        'overflow:visible !important;' +
1192        'text-overflow:clip !important;' +
1193      '}' +
1194    '</style>').appendTo('head');
1195  }
1196
1197  var updateImageSidebarHeading = function updateImageSidebarHeading() {
1198    var query = $('input[name="q"]').first().val() || getParameterByName('q', window.location.href) || '';
1199    query = $('<textarea/>').html(query).text().trim();
1200
1201    if (!query) return;
1202
1203    var headingText = query + ' Images';
1204    var $imageArea = $('#search-images-cse').closest('.card');
1205
1206    if (!$imageArea.length) {
1207      $imageArea = $('#search-images-cse').parent();
1208    }
1209
1210    $imageArea.find('.card-title, h1, h2, h3, h4, h5, h6').filter(function () {
1211      return $.trim($(this).text()) === 'Images' || $(this).attr('data-myallsearch-images-heading') === 'true';
1212    }).first().attr('data-myallsearch-images-heading', 'true').text(headingText);
1213  };
1214
1215  var addFindElsewhereToGoogleResults = function addFindElsewhereToGoogleResults() {
1216    $('.find-elsewhere').remove();
1217
1218    var $googleResults = $('.gsc-webResult.gsc-result').filter(function () {
1219      return $(this).find('.web-result').length > 0;
1220    });
1221
1222    if (!$googleResults.length) {
1223      return;
1224    }
1225
1226    var query = $('input[name="q"]').first().val() || getParameterByName('q', window.location.href) || '';
1227    query = $('<textarea/>').html(query).text();
1228
1229    if (!query) {
1230      return;
1231    }
1232
1233    var encodedQuery = encodeURIComponent(query);
1234    var searchIcon = '<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" style="display:block;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;"><circle cx="11" cy="11" r="7"></circle><path d="M20 20l-4-4"></path></svg>';
1235
1236    var html = '<div class="find-elsewhere" style="display:flex;align-items:center;flex-wrap:wrap;column-gap:10px;row-gap:10px;margin:24px 0 14px;font-family:inherit;">' +
1237      '<div style="display:inline-flex;align-items:center;gap:10px;margin-right:8px;color:#4f5358;font-size:0.9rem;font-weight:500;line-height:1.5;white-space:nowrap;">' +
1238        searchIcon + '<span>Find elsewhere</span>' +
1239      '</div>' +
1240      '<a class="find-elsewhere-button" href="https://www.google.com/search?q=' + encodedQuery + '" target="_blank" rel="noopener noreferrer" style="display:inline-flex;align-items:center;justify-content:center;height:44px;min-width:60px;padding:0 12px;border:1px solid #e1e4e8;border-radius:999px;background:#fff;color:#4f5358;text-decoration:none;font-size:0.9rem;font-weight:400;">Google<span class="find-elsewhere-privacy-warning"><strong>Privacy notice:</strong> Searches made using this link are handled by Google and may be tracked according to their privacy policy.</span></a>' +
1241      '<a class="find-elsewhere-button" href="https://www.bing.com/search?q=' + encodedQuery + '" target="_blank" rel="noopener noreferrer" style="display:inline-flex;align-items:center;justify-content:center;height:44px;min-width:60px;padding:0 12px;border:1px solid #e1e4e8;border-radius:999px;background:#fff;color:#4f5358;text-decoration:none;font-size:0.9rem;font-weight:400;">Bing<span class="find-elsewhere-privacy-warning"><strong>Privacy notice:</strong> Searches made using this link are handled by Bing and may be tracked according to their privacy policy.</span></a>' +
1242      '<a class="find-elsewhere-button" href="https://www.mojeek.com/search?q=' + encodedQuery + '" target="_blank" rel="noopener noreferrer" style="display:inline-flex;align-items:center;justify-content:center;height:44px;min-width:60px;padding:0 12px;border:1px solid #e1e4e8;border-radius:999px;background:#fff;color:#4f5358;text-decoration:none;font-size:0.9rem;font-weight:400;">Mojeek<span class="find-elsewhere-privacy-warning"><strong>Privacy notice:</strong> Searches made using this link are handled by Mojeek and may be subject to their privacy policy.</span></a>' +
1243    '</div>';
1244
1245    $googleResults.last().after(html);
1246  };
1247
1248  var setupNextSearchPageButton = function setupNextSearchPageButton() {
1249    var $cursor = $('.gsc-cursor').first();
1250    if (!$cursor.length) return;
1251
1252    var $current = $cursor.find('.gsc-cursor-current-page').first();
1253    var $prev = $current.prev('.gsc-cursor-page');
1254    var $next = $current.next('.gsc-cursor-page');
1255
1256    $cursor.find('.myallsearch-page-nav, .myallsearch-page-number').remove();
1257
1258    // Keep Google's real page controls in the DOM, but hide the numbers.
1259    $cursor.find('.gsc-cursor-page').each(function () {
1260      this.style.setProperty('display', 'none', 'important');
1261    });
1262
1263    var makeNavButton = function (label, target) {
1264      var $button = $('<button type="button" class="myallsearch-page-nav">' + label + '</button>');
1265
1266      $button.css({
1267        display: 'inline-flex',
1268        alignItems: 'center',
1269        justifyContent: 'center',
1270        gap: '8px',
1271        minWidth: '112px',
1272        height: '44px',
1273        padding: '0 24px',
1274        border: '1px solid rgba(0,0,0,.16)',
1275        borderRadius: '999px',
1276        background: '#fff',
1277        color: '#333',
1278        fontFamily: 'inherit',
1279        fontSize: '15px',
1280        fontWeight: '500',
1281        cursor: 'pointer'
1282      });
1283
1284      $button.on('click', function () {
1285        target[0].click();
1286      });
1287
1288      return $button;
1289    };
1290
1291    $cursor.css({
1292      display: 'flex',
1293      alignItems: 'center',
1294      justifyContent: 'center',
1295      gap: '12px',
1296      textAlign: 'center',
1297      padding: '8px 0 14px'
1298    });
1299
1300    if ($prev.length) {
1301      $cursor.append(makeNavButton('← Prev', $prev));
1302
1303      var currentPage = $.trim($current.text());
1304      if (currentPage) {
1305        var $pageNumber = $('<span class="myallsearch-page-number">Page ' + currentPage + '</span>');
1306        $pageNumber.css({
1307          display: 'inline-flex',
1308          alignItems: 'center',
1309          justifyContent: 'center',
1310          fontFamily: 'inherit',
1311          fontSize: '15px',
1312          fontWeight: '500',
1313          color: 'inherit',
1314          whiteSpace: 'nowrap'
1315        });
1316        $cursor.append($pageNumber);
1317      }
1318    }
1319
1320    if ($next.length) {
1321      $cursor.append(makeNavButton('Next →', $next));
1322    }
1323  };
1324
1325  var cleanGoogleSearchHash = function cleanGoogleSearchHash() {
1326    if (window.location.hash.indexOf('#gsc.') === 0) {
1327      window.history.replaceState(
1328        window.history.state,
1329        document.title,
1330        window.location.pathname + window.location.search
1331      );
1332    }
1333  };
1334
1335  var resultsRenderedCallback = function resultsRenderedCallback() {
1336    $('#search-loader').hide();
1337
1338    window.setTimeout(updateImageSidebarHeading, 0);
1339    window.setTimeout(updateImageSidebarHeading, 100);
1340    window.setTimeout(updateImageSidebarHeading, 300);
1341    $('#instant-answer').show();
1342    if (hasAccord) {
1343      $('#web-result-1').before(accords);
1344    }
1345
1346    // Google may finish attaching its final gsc-result wrappers just after this callback.
1347    window.setTimeout(addFindElsewhereToGoogleResults, 0);
1348    window.setTimeout(addFindElsewhereToGoogleResults, 100);
1349    window.setTimeout(addFindElsewhereToGoogleResults, 300);
1350
1351    window.setTimeout(setupNextSearchPageButton, 0);
1352    window.setTimeout(setupNextSearchPageButton, 100);
1353    window.setTimeout(setupNextSearchPageButton, 300);
1354    window.setTimeout(setupNextSearchPageButton, 700);
1355
1356    // Google CSE adds #gsc.tab / #gsc.q / #gsc.page to the address.
1357    // Remove that fragment after CSE has finished using it.
1358    window.setTimeout(cleanGoogleSearchHash, 100);
1359    window.setTimeout(cleanGoogleSearchHash, 400);
1360    window.setTimeout(cleanGoogleSearchHash, 800);
1361  };
1362
1363  var resultsReadyCallback = function resultsReadyCallback(name, q, promos, results, resultsDiv) {
1364    var items = '';
1365
1366    var makePromoParts = function makePromoParts(promo, id) {
1367      var thumb = '';
1368
1369      if (promo.image) {
1370        thumb = "<img src=\"".concat(promo.image.url, "\" class=\"web-thumb-img\" style=\"height:").concat(promo.image.height, "px;width:").concat(promo.image.width, "px\">");
1371      }
1372
1373      var target = '';
1374
1375      if (window.app.settings.new_window) {
1376        target = '_blank';
1377      }
1378
1379      var promoURL = getParameterByName('q', promo['url']);
1380      var promoDomain = promoURL.replace(/(^\w+:|^)\/\//, '').replace(/\/$/, "");
1381      var anchor = "<div class=\"web-result promo-result\" id=\"promo-".concat(id, "\">\n            <a class=\"web-result-title\" href=\"").concat(promoURL, "\" target=\"").concat(target, "\" rel=\"nofollow nopener noreferer\"><h3 class=\"web-result-title-heading\">\n            ").concat(promo['title'], "</h3></a>\n            <div class=\"web-result-domain\"><img src=\"https://www.google.com/s2/favicons?domain=").concat(promo['visibleUrl'], "\" class=\"web-result-favicon\">").concat(promoDomain, "</div>  ").concat(thumb, "\n            <p class=\"web-result-desc\">").concat(promo['content'], "</p>\n\n            </div>");
1382      return anchor;
1383    };
1384
1385    if (_typeof(promos) === 'object') {
1386      items += '<section class="promoted-results">';
1387
1388      for (var i in promos) {
1389        items += makePromoParts(promos[i], i);
1390      }
1391
1392      items += '</section>';
1393    }
1394
1395
1396var makeResultParts = function makeResultParts(result, id) {
1397      var thumb = '';
1398
1399      if (result.thumbnailImage && engine.showThumbnails) {
1400        thumb = "<img src=\"".concat(result.thumbnailImage.url, "\" class=\"web-thumb-img\">");
1401      }
1402      
1403      
1404
1405      var target = '';
1406
1407      if (window.app.settings.new_window) {
1408        target = '_blank';
1409      }
1410
1411      q = htmlEntities(q);
1412      var resURL = getParameterByName('q', result['url']);
1413      var resDomain = resURL.replace(/(^\w+:|^)\/\//, '').replace(/\/$/, "");
1414      var anchor = "<div class=\"web-result\" id=\"web-result-".concat(id, "\">\n            <a class=\"web-result-title\" href=\"").concat(resURL, "\" target=\"").concat(target, "\" rel=\"nofollow nopener noreferer\"><h3 class=\"web-result-title-heading\">\n            ").concat(result['title'], "</h3></a>\n            <div class=\"web-result-domain\"><img src=\"https://www.google.com/s2/favicons?domain=").concat(result['visibleUrl'], "\" class=\"web-result-favicon\">").concat(resDomain, "</div>  ").concat(thumb, "\n            <p class=\"web-result-desc\">").concat(result['content'], "</p>\n\n            </div>");
1415      return anchor;
1416    };
1417
1418    var extQuestions = [];
1419    if (results.length > 1) {
1420      accords = accordsMarkup;
1421      var i = 0;
1422      var answerDone = false;
1423      var i2 = 0;
1424      var _iterator = _createForOfIteratorHelper(results),
1425          _step;
1426      try {
1427        for (_iterator.s(); !(_step = _iterator.n()).done;) {
1428          var result = _step.value;
1429          if (result.richSnippet) {
1430            if (result.richSnippet.answer && result.richSnippet.answer[0] && result.richSnippet.question[0]) {
1431              if (i == 7) {
1432                break;
1433              }
1434
1435              i++;
1436              var expanded = 'false';
1437              var collapsed = 'collapsed';
1438              var collapse = 'collapse';
1439              var show = '';
1440
1441              if (i == 1) {
1442                expanded = 'true';
1443                show = 'show';
1444                collapse = 'collapse show';
1445              } 
1446              
1447              
1448              
1449              if(extQuestions.indexOf(result.richSnippet.question[0].name) == -1){
1450                  accords += "\n  <div class=\"expansion-panel list-group-item bg-transparent ".concat(show, "\">\n    <a aria-controls=\"collapse-").concat(i, "\" aria-expanded=\"").concat(expanded, "\" class=\"font-weight-bold expansion-panel-toggler ").concat(collapsed, "\" data-toggle=\"collapse\" href=\"#collapse-").concat(i, "\" id=\"collapse-heading-").concat(i, "\">\n    ").concat(result.richSnippet.question[0].name, "\n      <div class=\"expansion-panel-icon ml-3 text-black-secondary\">\n        <i class=\"collapsed-show\">").concat($theme.svgIcon('keyboard-arrow-down'), "</i>\n        <i class=\"collapsed-hide\">").concat($theme.svgIcon('keyboard-arrow-up'), "</i>\n      </div>\n    </a>\n    <div aria-labelledby=\"collapse-heading-").concat(i, "\" class=\"").concat(collapse, "\" data-parent=\"#answers-accordion\" id=\"collapse-").concat(i, "\">\n      <div class=\"expansion-panel-body\"><p class=\"card-text\">").concat(result.richSnippet.answer[0].text, "</p>\n      </div>\n    </div>\n  </div>");
1451              }
1452              extQuestions.push(result.richSnippet.question[0].name);
1453            }
1454          }
1455          i2++;
1456          items += makeResultParts(result, i2);
1457        }
1458      } catch (err) {
1459        _iterator.e(err);
1460      } finally {
1461        _iterator.f();
1462      }
1463
1464      accords += '</div></div>';
1465         if(searchSuggetions?.length > 0){
1466          let sidebarSuggestions = searchSuggetions.slice(0, 4);
1467          let suggestionHtml = '';
1468
1469          sidebarSuggestions.forEach(function(suggestion) {
1470            let suggestionUrl = '/search?q=' + encodeURIComponent(suggestion) + '&engine=1';
1471            suggestionHtml += `<a href="${suggestionUrl}" class="related-search-link"><svg class="svg-icon svg-sm"><use xlink:href="#search"></use></svg>${suggestion}</a>`;
1472          });
1473
1474          $('#related-searches-sidebar').html(suggestionHtml);
1475          $('#related-searches-card').show();
1476        } else {
1477          $('#related-searches-sidebar').empty();
1478          $('#related-searches-card').hide();
1479        }
1480
1481
1482      $(resultsDiv).html(items);
1483
1484      if (i > 3) {
1485        hasAccord = true;
1486      } else {
1487        hasAccord = false;
1488      }
1489    } else {
1490      q = htmlEntities(q);
1491      var plainQuery = $('<textarea/>').html(q).text();
1492      var encodedQuery = encodeURIComponent(plainQuery);
1493      var nothing = '<div class="no-results" style="padding:18px 0 10px;">' +
1494        '<p style="font-size:1.1rem;margin-bottom:6px;"><strong>No results found for &ldquo;' + q + '&rdquo;</strong></p>' +
1495        '<p style="margin-bottom:16px;">Try checking the spelling, using fewer words, or searching for something more general.</p>' +
1496        '<p style="margin-bottom:10px;font-weight:500;">Try this search elsewhere:</p>' +
1497        '<div style="display:flex;flex-wrap:wrap;gap:10px;">' +
1498          '<a href="https://www.google.com/search?q=' + encodedQuery + '" target="_blank" rel="noopener noreferrer" style="display:inline-block;padding:9px 15px;border:1px solid #ddd;border-radius:999px;text-decoration:none;color:inherit;">Google</a>' +
1499          '<a href="https://www.bing.com/search?q=' + encodedQuery + '" target="_blank" rel="noopener noreferrer" style="display:inline-block;padding:9px 15px;border:1px solid #ddd;border-radius:999px;text-decoration:none;color:inherit;">Bing</a>' +
1500          '<a href="https://www.mojeek.com/search?q=' + encodedQuery + '" target="_blank" rel="noopener noreferrer" style="display:inline-block;padding:9px 15px;border:1px solid #ddd;border-radius:999px;text-decoration:none;color:inherit;">Mojeek</a>' +
1501        '</div>' +
1502      '</div>';
1503      $(resultsDiv).html(nothing);
1504
1505      // No web results: hide the image sidebar card for this empty search.
1506      $('.search-images-card').hide();
1507    }
1508
1509    return true;
1510  };
1511
1512  window.__gcse || (window.__gcse = {});
1513  window.__gcse.searchCallbacks = {
1514    web: {
1515      ready: resultsReadyCallback,
1516      rendered: resultsRenderedCallback
1517    },
1518    image: {
1519      rendered: resultsRenderedCallback
1520    }
1521  };
1522  dynamicThemeEvents();
1523  $(window).on('scroll load', function (event) {
1524    var scroll = $(window).scrollTop();
1525    if (scroll > 56) {
1526      $('body').addClass('navbar-active');
1527      $('#site-navbar').fadeIn(500).addClass("navbar-scrolled");
1528    } else {
1529      $('#site-navbar').fadeIn(500).removeClass("navbar-scrolled");
1530      $('body').removeClass('navbar-active');
1531    }
1532  });
1533  $(document).on('click', '[data-engine-id]', function (event) {
1534    event.preventDefault();
1535    var el = $(this);
1536    var id = el.data('engine-id');
1537    var target = el.data('target');
1538    var textTarget = el.data('text-target');
1539
1540    if (target) {
1541      $(target).val(id);
1542    }
1543
1544    if (textTarget) {
1545      $(textTarget).text(el.text());
1546    }
1547
1548    $('[data-engine-active="true"]').removeClass('active').attr('data-engine-active', false);
1549    $('[data-engine-id="' + id + '"]').attr('data-engine-active', true).addClass('active');
1550  }); // Enable Popovers
1551
1552  $('body').popover({
1553    selector: '[data-toggle="popover"]',
1554    html: true
1555  });
1556  $(document).on('change', '[data-file-preview]', function (event) {
1557    var input = this;
1558    var target = $($(this).data('file-preview'));
1559
1560    if (input.files && input.files[0]) {
1561      var reader = new FileReader();
1562
1563      reader.onload = function (e) {
1564        target.css('background-image', 'url(' + e.target.result + ')');
1565      };
1566
1567      reader.readAsDataURL(input.files[0]);
1568    }
1569  });
1570});

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.