PageSourceSearch

http://myadmin.biemer.bplaced.net/js/dist/ajax.js?v=5.2.0

js biemer.bplaced.net collected 2026-10-09 23:45:22 UTC 29,575 bytes, 963 lines download raw bytes

1/**
2 * This object handles ajax requests for pages. It also
3 * handles the reloading of the main menu and scripts.
4 *
5 * @test-module AJAX
6 */
7var AJAX = {
8  /**
9   * @var {boolean} active Whether we are busy
10   */
11  active: false,
12
13  /**
14   * @var {object} source The object whose event initialized the request
15   */
16  source: null,
17
18  /**
19   * @var {object} xhr A reference to the ajax request that is currently running
20   */
21  xhr: null,
22
23  /**
24   * @var {object} lockedTargets, list of locked targets
25   */
26  lockedTargets: {},
27  // eslint-disable-next-line valid-jsdoc
28
29  /**
30   * @var {Function} callback Callback to execute after a successful request
31   *                          Used by CommonActions from common.js
32   */
33  callback: function () {},
34
35  /**
36   * @var {boolean} debug Makes noise in your Firebug console
37   */
38  debug: false,
39
40  /**
41   * @var {object} $msgbox A reference to a jQuery object that links to a message
42   *                     box that is generated by Functions.ajaxShowMessage()
43   */
44  $msgbox: null,
45
46  /**
47   * Given the filename of a script, returns a hash to be
48   * used to refer to all the events registered for the file
49   *
50   * @param {string} key key The filename for which to get the event name
51   *
52   * @return {number}
53   */
54  hash: function (key) {
55    var newKey = key;
56    /* https://burtleburtle.net/bob/hash/doobs.html#one */
57
58    newKey += '';
59    var len = newKey.length;
60    var hash = 0;
61    var i = 0;
62
63    for (; i < len; ++i) {
64      hash += newKey.charCodeAt(i);
65      hash += hash << 10;
66      hash ^= hash >> 6;
67    }
68
69    hash += hash << 3;
70    hash ^= hash >> 11;
71    hash += hash << 15;
72    return Math.abs(hash);
73  },
74
75  /**
76   * Registers an onload event for a file
77   *
78   * @param {string} file   The filename for which to register the event
79   * @param {Function} func The function to execute when the page is ready
80   *
81   * @return {self} For chaining
82   */
83  registerOnload: function (file, func) {
84    var eventName = 'onload_' + AJAX.hash(file);
85    $(document).on(eventName, func);
86
87    if (this.debug) {
88      // eslint-disable-next-line no-console
89      console.log( // no need to translate
90      'Registered event ' + eventName + ' for file ' + file);
91    }
92
93    return this;
94  },
95
96  /**
97   * Registers a teardown event for a file. This is useful to execute functions
98   * that unbind events for page elements that are about to be removed.
99   *
100   * @param {string} file   The filename for which to register the event
101   * @param {Function} func The function to execute when
102   *                        the page is about to be torn down
103   *
104   * @return {self} For chaining
105   */
106  registerTeardown: function (file, func) {
107    var eventName = 'teardown_' + AJAX.hash(file);
108    $(document).on(eventName, func);
109
110    if (this.debug) {
111      // eslint-disable-next-line no-console
112      console.log( // no need to translate
113      'Registered event ' + eventName + ' for file ' + file);
114    }
115
116    return this;
117  },
118
119  /**
120   * Called when a page has finished loading, once for every
121   * file that registered to the onload event of that file.
122   *
123   * @param {string} file The filename for which to fire the event
124   *
125   * @return {void}
126   */
127  fireOnload: function (file) {
128    var eventName = 'onload_' + AJAX.hash(file);
129    $(document).trigger(eventName);
130
131    if (this.debug) {
132      // eslint-disable-next-line no-console
133      console.log( // no need to translate
134      'Fired event ' + eventName + ' for file ' + file);
135    }
136  },
137
138  /**
139   * Called just before a page is torn down, once for every
140   * file that registered to the teardown event of that file.
141   *
142   * @param {string} file The filename for which to fire the event
143   *
144   * @return {void}
145   */
146  fireTeardown: function (file) {
147    var eventName = 'teardown_' + AJAX.hash(file);
148    $(document).triggerHandler(eventName);
149
150    if (this.debug) {
151      // eslint-disable-next-line no-console
152      console.log( // no need to translate
153      'Fired event ' + eventName + ' for file ' + file);
154    }
155  },
156
157  /**
158   * function to handle lock page mechanism
159   *
160   * @param event the event object
161   *
162   * @return {void}
163   */
164  lockPageHandler: function (event) {
165    // don't consider checkbox event
166    if (typeof event.target !== 'undefined') {
167      if (event.target.type === 'checkbox') {
168        return;
169      }
170    }
171
172    var newHash = null;
173    var oldHash = null;
174    var lockId; // CodeMirror lock
175
176    if (event.data.value === 3) {
177      newHash = event.data.content;
178      oldHash = true;
179      lockId = 'cm';
180    } else {
181      // Don't lock on enter.
182      if (0 === event.charCode) {
183        return;
184      }
185
186      lockId = $(this).data('lock-id');
187
188      if (typeof lockId === 'undefined') {
189        return;
190      }
191      /*
192       * @todo Fix Code mirror does not give correct full value (query)
193       * in textarea, it returns only the change in content.
194       */
195
196
197      if (event.data.value === 1) {
198        newHash = AJAX.hash($(this).val());
199      } else {
200        newHash = AJAX.hash($(this).is(':checked'));
201      }
202
203      oldHash = $(this).data('val-hash');
204    } // Set lock if old value !== new value
205    // otherwise release lock
206
207
208    if (oldHash !== newHash) {
209      AJAX.lockedTargets[lockId] = true;
210    } else {
211      delete AJAX.lockedTargets[lockId];
212    }
212 // Show lock icon if locked targets is not empty.
213    // otherwise remove lock icon
214
215
216    if (!jQuery.isEmptyObject(AJAX.lockedTargets)) {
217      $('#lock_page_icon').html(Functions.getImage('s_lock', Messages.strLockToolTip).toString());
218    } else {
219      $('#lock_page_icon').html('');
220    }
221  },
222
223  /**
224   * resets the lock
225   *
226   * @return {void}
227   */
228  resetLock: function () {
229    AJAX.lockedTargets = {};
230    $('#lock_page_icon').html('');
231  },
232  handleMenu: {
233    replace: function (content) {
234      $('#floating_menubar').html(content) // Remove duplicate wrapper
235      // TODO: don't send it in the response
236      .children().first().remove();
237      $('#topmenu').menuResizer(Functions.mainMenuResizerCallback);
238    }
239  },
240
241  /**
242   * Event handler for clicks on links and form submissions
243   *
244   * @param {KeyboardEvent} event Event data
245   *
246   * @return {boolean | void}
247   */
248  requestHandler: function (event) {
249    // In some cases we don't want to handle the request here and either
250    // leave the browser deal with it natively (e.g: file download)
251    // or leave an existing ajax event handler present elsewhere deal with it
252    var href = $(this).attr('href');
253
254    if (typeof event !== 'undefined' && (event.shiftKey || event.ctrlKey || event.metaKey)) {
255      return true;
256    } else if ($(this).attr('target')) {
257      return true;
258    } else if ($(this).hasClass('ajax') || $(this).hasClass('disableAjax')) {
259      // reset the lockedTargets object, as specified AJAX operation has finished
260      AJAX.resetLock();
261      return true;
262    } else if (href && href.match(/^#/)) {
263      return true;
264    } else if (href && href.match(/^mailto/)) {
265      return true;
266    } else if ($(this).hasClass('ui-datepicker-next') || $(this).hasClass('ui-datepicker-prev')) {
267      return true;
268    }
269
270    if (typeof event !== 'undefined') {
271      event.preventDefault();
272      event.stopImmediatePropagation();
273    } // triggers a confirm dialog if:
274    // the user has performed some operations on loaded page
275    // the user clicks on some link, (won't trigger for buttons)
276    // the click event is not triggered by script
277
278
279    if (typeof event !== 'undefined' && event.type === 'click' && event.isTrigger !== true && !jQuery.isEmptyObject(AJAX.lockedTargets) && confirm(Messages.strConfirmNavigation) === false) {
280      return false;
281    }
282
283    AJAX.resetLock();
284    var isLink = !!href || false;
285    var previousLinkAborted = false;
286
287    if (AJAX.active === true) {
288      // Cancel the old request if abortable, when the user requests
289      // something else. Otherwise silently bail out, as there is already
290      // a request well in progress.
291      if (AJAX.xhr) {
292        // In case of a link request, attempt aborting
293        AJAX.xhr.abort();
294
295        if (AJAX.xhr.status === 0 && AJAX.xhr.statusText === 'abort') {
296          // If aborted
297          AJAX.$msgbox = Functions.ajaxShowMessage(Messages.strAbortedRequest);
298          AJAX.active = false;
299          AJAX.xhr = null;
300          previousLinkAborted = true;
301        } else {
302          // If can't abort
303          return false;
304        }
305      } else {
306        // In case submitting a form, don't attempt aborting
307        return false;
308      }
309    }
310
311    AJAX.source = $(this);
312    $('html, body').animate({
313      scrollTop: 0
314    }, 'fast');
315    var url = isLink ? href : $(this).attr('action');
316    var argsep = CommonParams.get('arg_separator');
317    var params = 'ajax_request=true' + argsep + 'ajax_page_request=true';
318    var dataPost = AJAX.source.getPostData();
319
320    if (!isLink) {
321      params += argsep + $(this).serialize();
322    } else if (dataPost) {
323      params += argsep + dataPost;
324      isLink = false;
325    }
326
327    if (AJAX.debug) {
328      // eslint-disable-next-line no-console
329      console.log('Loading: ' + url); // no need to translate
330    }
331
332    if (isLink) {
333      AJAX.active = true;
334      AJAX.$msgbox = Functions.ajaxShowMessage(); // Save reference for the new link request
335
336      AJAX.xhr = $.get(url, params, AJAX.responseHandler);
337      var state = {
338        url: href
339      };
340
341      if (previousLinkAborted) {
342        // hack: there is already an aborted entry on stack
343        // so just modify the aborted one
344        history.replaceState(state, null, href);
345      } else {
346        history.pushState(state, null, href);
347      }
348    } else {
349      /**
350       * Manually fire the onsubmit event for the form, if any.
351       * The event was saved in the jQuery data object by an onload
352       * handler defined below. Workaround for bug #3583316
353       */
354      var onsubmit = $(this).data('onsubmit'); // Submit the request if there is no onsubmit handler
355      // or if it returns a value that evaluates to true
356
357      if (typeof onsubmit !== 'function' || onsubmit.apply(this, [event])) {
358        AJAX.active = true;
359        AJAX.$msgbox = Functions.ajaxShowMessage();
360
361        if ($(this).attr('id') === 'login_form') {
362          $.post(url, params, AJAX.loginResponseHandler);
363        } else {
364          $.post(url, params, AJAX.responseHandler);
365        }
366      }
367    }
368  },
369
370  /**
371   * Response handler to handle login request from login modal after session expiration
372   *
373   * To refer to self use 'AJAX', instead of 'this' as this function
374   * is called in the jQuery context.
375   *
376   * @param {object} data Event data
377   *
378   * @return {void}
379   */
380  loginResponseHandler: function (data) {
381    if (typeof data === 'undefined' || data === null) {
382      return;
383    }
384
385    Functions.ajaxRemoveMessage(AJAX.$msgbox);
386    CommonParams.set('token', data.new_token);
387    AJAX.scriptHandler.load([]);
388
389    if (data.displayMessage) {
390      $('#page_content').prepend(data.displayMessage);
391      Functions.highlightSql($('#page_content'));
392    }
393
394    $('#pma_errors').remove();
395    var msg = '';
396
397    if (data.errSubmitMsg) {
398      msg = data.errSubmitMsg;
399    }
400
401    if (data.errors) {
402      $('<div></div>', {
403        id: 'pma_errors',
404        class: 'clearfloat d-print-none'
405      }).insertAfter('#selflink').append(data.errors); // bind for php error reporting forms (bottom)
406
407      $('#pma_ignore_errors_bottom').on('click', function (e) {
408        e.preventDefault();
409        Functions.ignorePhpErrors();
410      });
411      $('#pma_ignore_all_errors_bottom').on('click', function (e) {
412        e.preventDefault();
413        Functions.ignorePhpErrors(false);
414      }); // In case of 'sendErrorReport'='always'
415      // submit the hidden error reporting form.
416
417      if (data.sendErrorAlways === '1' && data.stopErrorReportLoop !== '1') {
418        $('#pma_report_errors_form').trigger('submit');
419        Functions.ajaxShowMessage(Messages.phpErrorsBeingSubmitted, false);
420        $('html, body').animate({
421          scrollTop: $(document).height()
422        }, 'slow');
423      } else if (data.promptPhpErrors) {
424        // otherwise just prompt user if it is set so.
425        msg = msg + Messages.phpErrorsFound; // scroll to bottom where all the errors are displayed.
426
427        $('html, body').animate({
428          scrollTop: $(document).height()
429        }, 'slow');
430      }
431    }
432
433    Functions.ajaxShowMessage(msg, false); // bind for php error reporting forms (popup)
434
435    $('#pma_ignore_errors_popup').on('click', function () {
436      Functions.ignorePhpErrors();
437    });
438    $('#pma_ignore_all_errors_popup').on('click', function () {
439      Functions.ignorePhpErrors(false);
440    });
441
442    if (typeof data.success !== 'undefined' && data.success) {
443      // reload page if user trying to login has changed
444      if (CommonParams.get('user') !== data.params.user) {
445        window.location = 'index.php';
446        Functions.ajaxShowMessage(Messages.strLoading, false);
447        AJAX.active = false;
448        AJAX.xhr = null;
449        return;
450      } // remove the login modal if the login is successful otherwise show error.
451
452
453      if (typeof data.logged_in !== 'undefined' && data.logged_in === 1) {
454        if ($('#modalOverlay').length) {
455          $('#modalOverlay').remove();
456        }
457
458        $('fieldset.disabled_for_expiration').removeAttr('disabled').removeClass('disabled_for_expiration');
459        AJAX.fireTeardown('functions.js');
460        AJAX.fireOnload('functions.js');
461      }
462
463      if (typeof data.new_token !== 'undefined') {
464        $('input[name=token]').val(data.new_token);
465      }
466    } else if (typeof data.logged_in !== 'undefined' && data.logged_in === 0) {
467      $('#modalOverlay').replaceWith(data.error);
468    } else {
469      Functions.ajaxShowMessage(data.error, false);
470      AJAX.active = false;
471      AJAX.xhr = null;
472      Functions.handleRedirectAndReload(data);
473
474      if (data.fieldWithError) {
475        $(':input.error').removeClass('error');
476        $('#' + data.fieldWithError).addClass('error');
477      }
478    }
479  },
480
481  /**
482   * Called after the request that was initiated by this.requestHandler()
483   * has completed successfully or with a caught error. For completely
484   * failed requests or requests with uncaught errors, see the .ajaxError
485   * handler at the bottom of this file.
486   *
487   * To refer to self use 'AJAX', instead of 'this' as this function
488   * is called in the jQuery context.
489   *
490   * @param {object} data Event data
491   *
492   * @return {void}
493   */
494  responseHandler: function (data) {
495    if (typeof data === 'undefined' || data === null) {
496      return;
497    }
498
499    if (typeof data.success !== 'undefined' && data.success) {
500      $('html, body').animate({
501        scrollTop: 0
502      }, 'fast');
503      Functions.ajaxRemoveMessage(AJAX.$msgbox);
504
505      if (data.redirect) {
506        Functions.ajaxShowMessage(data.redirect, false);
507        AJAX.active = false;
508        AJAX.xhr = null;
509        return;
510      }
511
512      AJAX.scriptHandler.reset(function () {
513        if (data.reloadNavigation) {
514          Navigation.reload();
515        }
516
517        if (data.title) {
518          $('title').replaceWith(data.title);
519        }
520
521        if (data.menu) {
522          var state = {
523            url: data.selflink,
524            menu: data.menu
525          };
526          history.replaceState(state, null);
527          AJAX.handleMenu.replace(data.menu);
528        }
529
530        if (data.disableNaviSettings) {
531          Navigation.disableSettings();
532        } else {
533          Navigation.ensureSettings(data.selflink);
534        } // Remove all containers that may have
535        // been added outside of #page_content
536
537
538        $('body').children().not('#pma_navigation').not('#floating_menubar').not('#page_nav_icons').not('#page_content').not('#selflink').not('#pma_header').not('#pma_footer').not('#pma_demo').not('#pma_console_container').not('#prefs_autoload').remove(); // Replace #page_content with new content
539
540        if (data.message && data.message.length > 0) {
541          $('#page_content').replaceWith('<div id=\'page_content\'>' + data.message + '</div>');
542          Functions.highlightSql($('#page_content'));
543          Functions.checkNumberOfFields();
544        }
545
546        if (data.selflink) {
547          var source = data.selflink.split('?')[0]; // Check for faulty links
548
549          var $selflinkReplace = {
550            'index.php?route=/import': 'index.php?route=/table/sql',
551            'index.php?route=/table/chart': 'index.php?route=/sql',
552            'index.php?route=/table/gis-visualization': 'index.php?route=/sql'
553          };
554
555          if ($selflinkReplace[source]) {
556            var replacement = $selflinkReplace[source];
557            data.selflink = data.selflink.replace(source, replacement);
558          }
559
560          $('#selflink').find('> a').attr('href', data.selflink);
561        }
562
563        if (data.params) {
564          CommonParams.setAll(data.params);
565        }
566
567        if (data.scripts) {
568          AJAX.scriptHandler.load(data.scripts);
569        }
570
571        if (data.displayMessage) {
572          $('#page_content').prepend(data.displayMessage);
573          Functions.highlightSql($('#page_content'));
574        }
575
576        $('#pma_errors').remove();
577        var msg = '';
578
579        if (data.errSubmitMsg) {
580          msg = data.errSubmitMsg;
581        }
582
583        if (data.errors) {
584          $('<div></div>', {
585            id: 'pma_errors',
586            class: 'clearfloat d-print-none'
587          }).insertAfter('#selflink').append(data.errors); // bind for php error reporting forms (bottom)
588
589          $('#pma_ignore_errors_bottom').on('click', function (e) {
590            e.preventDefault();
591            Functions.ignorePhpErrors();
592          });
593          $('#pma_ignore_all_errors_bottom').on('click', function (e) {
594            e.preventDefault();
595            Functions.ignorePhpErrors(false);
596          }); // In case of 'sendErrorReport'='always'
597          // submit the hidden error reporting form.
598
599          if (data.sendErrorAlways === '1' && data.stopErrorReportLoop !== '1') {
600            $('#pma_report_errors_form').trigger('submit');
601            Functions.ajaxShowMessage(Messages.phpErrorsBeingSubmitted, false);
602            $('html, body').animate({
603              scrollTop: $(document).height()
604            }, 'slow');
605          } else if (data.promptPhpErrors) {
606            // otherwise just prompt user if it is set so.
607            msg = msg + Messages.phpErrorsFound; // scroll to bottom where all the errors are displayed.
608
609            $('html, body').animate({
610              scrollTop: $(document).height()
611            }, 'slow');
612          }
613        }
614
615        Functions.ajaxShowMessage(msg, false); // bind for php error reporting forms (popup)
616
617        $('#pma_ignore_errors_popup').on('click', function () {
618          Functions.ignorePhpErrors();
619        });
620        $('#pma_ignore_all_errors_popup').on('click', function () {
621          Functions.ignorePhpErrors(false);
622        });
623
624        if (typeof AJAX.callback === 'function') {
625          AJAX.callback.call();
626        }
627
628        AJAX.callback = function () {};
629      });
630    } else {
631      Functions.ajaxShowMessage(data.error, false);
632      Functions.ajaxRemoveMessage(AJAX.$msgbox);
633      var $ajaxError = $('<div></div>');
634      $ajaxError.attr({
635        'id': 'ajaxError'
636      });
637      $('#page_content').append($ajaxError);
638      $ajaxError.html(data.error);
639      $('html, body').animate({
640        scrollTop: $(document).height()
641      }, 200);
642      AJAX.active = false;
643      AJAX.xhr = null;
644      Functions.handleRedirectAndReload(data);
645
646      if (data.fieldWithError) {
647        $(':input.error').removeClass('error');
648        $('#' + data.fieldWithError).addClass('error');
649      }
650    }
651  },
652
653  /**
654   * This object is in charge of downloading scripts,
655   * keeping track of what's downloaded and firing
656   * the onload event for them when the page is ready.
657   */
658  scriptHandler: {
659    /**
660     * @var {string[]} scripts The list of files already downloaded
661     */
662    scripts: [],
663
664    /**
665     * @var {string} scriptsVersion version of phpMyAdmin from which the
666     *                              scripts have been loaded
667     */
668    scriptsVersion: null,
669
670    /**
671     * @var {string[]} scriptsToBeLoaded The list of files that
672     *                                   need to be downloaded
673     */
674    scriptsToBeLoaded: [],
675
676    /**
677     * @var {string[]} scriptsToBeFired The list of files for which
678     *                                  to fire the onload and unload events
679     */
680    scriptsToBeFired: [],
681    scriptsCompleted: false,
682
683    /**
684     * Records that a file has been downloaded
685     *
686     * @param {string} file The filename
687     * @param {string} fire Whether this file will be registering
688     *                      onload/teardown events
689     *
690     * @return {self} For chaining
691     */
692    add: function (file, fire) {
693      this.scripts.push(file);
694
695      if (fire) {
696        // Record whether to fire any events for the file
697        // This is necessary to correctly tear down the initial page
698        this.scriptsToBeFired.push(file);
699      }
700
701      return this;
702    },
703
704    /**
705     * Download a list of js files in one request
706     *
707     * @param {string[]} files An array of filenames and flags
708     * @param {Function} callback
709     *
710     * @return {void}
711     */
712    load: function (files, callback) {
713      var self = this;
714      var i; // Clear loaded scripts if they are from another version of phpMyAdmin.
715      // Depends on common params being set before loading scripts in responseHandler
716
717      if (self.scriptsVersion === null) {
718        self.scriptsVersion = CommonParams.get('version');
719      } else if (self.scriptsVersion !== CommonParams.get('version')) {
720        self.scripts = [];
721        self.scriptsVersion = CommonParams.get('version');
722      }
723
724      self.scriptsCompleted = false;
725      self.scriptsToBeFired = []; // We need to first complete list of files to load
726      // as next loop will directly fire requests to load them
727      // and that triggers removal of them from
728      // self.scriptsToBeLoaded
729
730      for (i in files) {
731        self.scriptsToBeLoaded.push(files[i].name);
732
733        if (files[i].fire) {
734          self.scriptsToBeFired.push(files[i].name);
735        }
736      }
737
738      for (i in files) {
739        var script = files[i].name; // Only for scripts that we don't already have
740
741        if ($.inArray(script, self.scripts) === -1) {
742          this.add(script);
743          this.appendScript(script, callback);
744        } else {
745          self.done(script, callback);
746        }
747      } // Trigger callback if there is nothing else to load
748
749
750      self.done(null, callback);
751    },
752
753    /**
754     * Called whenever all files are loaded
755     *
756     * @param {string} script
757     * @param {Function?} callback
758     *
759     * @return {void}
760     */
761    done: function (script, callback) {
762      if ($.inArray(script, this.scriptsToBeFired)) {
763        AJAX.fireOnload(script);
764      }
765
766      if ($.inArray(script, this.scriptsToBeLoaded)) {
767        this.scriptsToBeLoaded.splice($.inArray(script, this.scriptsToBeLoaded), 1);
768      }
769
770      if (script === null) {
771        this.scriptsCompleted = true;
772      }
773      /* We need to wait for last signal (with null) or last script load */
774
775
776      AJAX.active = this.scriptsToBeLoaded.length > 0 || !this.scriptsCompleted;
777      /* Run callback on last script */
778
779      if (!AJAX.active && typeof callback === 'function') {
780        callback();
781      }
782    },
783
784    /**
785     * Appends a script element to the head to load the scripts
786     *
787     * @param {string} name
788     * @param {Function} callback
789     *
790     * @return {void}
791     */
792    appendScript: function (name, callback) {
793      var head = document.head || document.getElementsByTagName('head')[0];
794      var script = document.createElement('script');
795      var self = this;
796      script.type = 'text/javascript';
797      var file = name.indexOf('vendor/') !== -1 ? name : 'dist/' + name;
798      script.src = 'js/' + file + '?' + 'v=' + encodeURIComponent(CommonParams.get('version'));
799      script.async = false;
800
801      script.onload = function () {
802        self.done(name, callback);
803      };
804
805      head.appendChild(script);
806    },
807
808    /**
809     * Fires all the teardown event handlers for the current page
810     * and rebinds all forms and links to the request handler
811     *
812     * @param {Function} callback The callback to call after resetting
813     *
814     * @return {void}
815     */
816    reset: function (callback) {
817      for (var i in this.scriptsToBeFired) {
818        AJAX.fireTeardown(this.scriptsToBeFired[i]);
819      }
820
821      this.scriptsToBeFired = [];
822      /**
823       * Re-attach a generic event handler to clicks
824       * on pages and submissions of forms
825       */
826
827      $(document).off('click', 'a').on('click', 'a', AJAX.requestHandler);
828      $(document).off('submit', 'form').on('submit', 'form', AJAX.requestHandler);
829      callback();
830    }
831  }
832};
833/**
834 * Here we register a function that will remove the onsubmit event from all
835 * forms that will be handled by the generic page loader. We then save this
836 * event handler in the "jQuery data", so that we can fire it up later in
837 * AJAX.requestHandler().
838 *
839 * See bug #3583316
840 */
841
842AJAX.registerOnload('functions.js', function () {
843  // Registering the onload event for functions.js
844  // ensures that it will be fired for all pages
845  $('form').not('.ajax').not('.disableAjax').each(function () {
846    if ($(this).attr('onsubmit')) {
847      $(this).data('onsubmit', this.onsubmit).attr('onsubmit', '');
848    }
849  });
850  var $pageContent = $('#page_content');
851  /**
852   * Workaround for passing submit button name,value on ajax form submit
853   * by appending hidden element with submit button name and value.
854   */
855
856  $pageContent.on('click', 'form input[type=submit]', function () {
857    var buttonName = $(this).attr('name');
858
859    if (typeof buttonName === 'undefined') {
860      return;
861    }
862
863    $(this).closest('form').append($('<input>', {
864      'type': 'hidden',
865      'name': buttonName,
866      'value': $(this).val()
867    }));
868  });
869  /**
870   * Attach event listener to events when user modify visible
871   * Input,Textarea and select fields to make changes in forms
872   */
873
874  $pageContent.on('keyup change', 'form.lock-page textarea, ' + 'form.lock-page input[type="text"], ' + 'form.lock-page input[type="number"], ' + 'form.lock-page select', {
875    value: 1
876  }, AJAX.lockPageHandler);
877  $pageContent.on('change', 'form.lock-page input[type="checkbox"], ' + 'form.lock-page input[type="radio"]', {
878    value: 2
879  }, AJAX.lockPageHandler);
880  /**
881   * Reset lock when lock-page form reset event is fired
882   * Note: reset does not bubble in all browser so attach to
883   * form directly.
884   */
885
886  $('form.lock-page').on('reset', function () {
887    AJAX.resetLock();
888  });
889});
890/**
891 * Page load event handler
892 */
893
894$(function () {
895  var menuContent = $('<div></div>').append($('#server-breadcrumb').clone()).append($('#topmenucontainer').clone()).html(); // set initial state reload
896
897  var initState = 'state' in window.history && window.history.state !== null;
898  var initURL = $('#selflink').find('> a').attr('href') || location.href;
899  var state = {
900    url: initURL,
901    menu: menuContent
902  };
903  history.replaceState(state, null);
904  $(window).on('popstate', function (event) {
905    var initPop = !initState && location.href === initURL;
906    initState = true; // check if popstate fired on first page itself
907
908    if (initPop) {
909      return;
910    }
911
912    var state = event.originalEvent.state;
913
914    if (state && state.menu) {
915      AJAX.$msgbox = Functions.ajaxShowMessage();
916      var params = 'ajax_request=true' + CommonParams.get('arg_separator') + 'ajax_page_request=true';
917      var url = state.url || location.href;
918      $.get(url, params, AJAX.responseHandler); // TODO: Check if sometimes menu is not retrieved from server,
919      // Not sure but it seems menu was missing only for printview which
920      // been removed lately, so if it's right some dead menu checks/fallbacks
921      // may need to be removed from this file and Header.php
922      // AJAX.handleMenu.replace(event.originalEvent.state.menu);
923    }
924  });
925});
926/**
927 * Attach a generic event handler to clicks
928 * on pages and submissions of forms
929 */
930
931$(document).on('click', 'a', AJAX.requestHandler);
932$(document).on('submit', 'form', AJAX.requestHandler);
933/**
934 * Gracefully handle fatal server errors
935 * (e.g: 500 - Internal server error)
936 */
937
938$(document).on('ajaxError', function (event, request) {
939  if (AJAX.debug) {
940    // eslint-disable-next-line no-console
941    console.log('AJAX error: status=' + request.status + ', text=' + request.statusText);
942  } // Don't handle aborted requests
943
944
945  if (request.status !== 0 || request.statusText !== 'abort') {
946    var details = '';
947    var state = request.state();
948
949    if (request.status !== 0) {
950      details += '<div>' + Functions.escapeHtml(Functions.sprintf(Messages.strErrorCode, request.status)) + '</div>';
951    }
952
953    details += '<div>' + Functions.escapeHtml(Functions.sprintf(Messages.strErrorText, request.statusText + ' (' + state 
953+ ')')) + '</div>';
954
955    if (state === 'rejected' || state === 'timeout') {
956      details += '<div>' + Functions.escapeHtml(Messages.strErrorConnection) + '</div>';
957    }
958
959    Functions.ajaxShowMessage('<div class="alert alert-danger" role="alert">' + Messages.strErrorProcessingRequest + details + '</div>', false);
960    AJAX.active = false;
961    AJAX.xhr = null;
962  }
963});

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.