Billing module improvements.
[openemr.git] / phpmyadmin / js / ajax.js
blobf24971a8da1af71257191fdb02bde9051f3bdbb4
1 /* vim: set expandtab sw=4 ts=4 sts=4: */
2 /**
3  * This object handles ajax requests for pages. It also
4  * handles the reloading of the main menu and scripts.
5  */
6 var AJAX = {
7     /**
8      * @var bool active Whether we are busy
9      */
10     active: false,
11     /**
12      * @var object source The object whose event initialized the request
13      */
14     source: null,
15     /**
16      * @var object xhr A reference to the ajax request that is currently running
17      */
18     xhr: null,
19     /**
20      * @var object lockedTargets, list of locked targets
21      */
22     lockedTargets: {},
23     /**
24      * @var function Callback to execute after a successful request
25      *               Used by PMA_commonFunctions from common.js
26      */
27     _callback: function () {},
28     /**
29      * @var bool _debug Makes noise in your Firebug console
30      */
31     _debug: false,
32     /**
33      * @var object $msgbox A reference to a jQuery object that links to a message
34      *                     box that is generated by PMA_ajaxShowMessage()
35      */
36     $msgbox: null,
37     /**
38      * Given the filename of a script, returns a hash to be
39      * used to refer to all the events registered for the file
40      *
41      * @param key string key The filename for which to get the event name
42      *
43      * @return int
44      */
45     hash: function (key) {
46         /* http://burtleburtle.net/bob/hash/doobs.html#one */
47         key += "";
48         var len = key.length, hash = 0, i = 0;
49         for (; i < len; ++i) {
50             hash += key.charCodeAt(i);
51             hash += (hash << 10);
52             hash ^= (hash >> 6);
53         }
54         hash += (hash << 3);
55         hash ^= (hash >> 11);
56         hash += (hash << 15);
57         return Math.abs(hash);
58     },
59     /**
60      * Registers an onload event for a file
61      *
62      * @param file string   file The filename for which to register the event
63      * @param func function func The function to execute when the page is ready
64      *
65      * @return self For chaining
66      */
67     registerOnload: function (file, func) {
68         var eventName = 'onload_' + AJAX.hash(file);
69         $(document).bind(eventName, func);
70         if (this._debug) {
71             console.log(
72                 // no need to translate
73                 "Registered event " + eventName + " for file " + file
74             );
75         }
76         return this;
77     },
78     /**
79      * Registers a teardown event for a file. This is useful to execute functions
80      * that unbind events for page elements that are about to be removed.
81      *
82      * @param string   file The filename for which to register the event
83      * @param function func The function to execute when
84      *                      the page is about to be torn down
85      *
86      * @return self For chaining
87      */
88     registerTeardown: function (file, func) {
89         var eventName = 'teardown_' + AJAX.hash(file);
90         $(document).bind(eventName, func);
91         if (this._debug) {
92             console.log(
93                 // no need to translate
94                 "Registered event " + eventName + " for file " + file
95             );
96         }
97         return this;
98     },
99     /**
100      * Called when a page has finished loading, once for every
101      * file that registered to the onload event of that file.
102      *
103      * @param string file The filename for which to fire the event
104      *
105      * @return void
106      */
107     fireOnload: function (file) {
108         var eventName = 'onload_' + AJAX.hash(file);
109         $(document).trigger(eventName);
110         if (this._debug) {
111             console.log(
112                 // no need to translate
113                 "Fired event " + eventName + " for file " + file
114             );
115         }
116     },
117     /**
118      * Called just before a page is torn down, once for every
119      * file that registered to the teardown event of that file.
120      *
121      * @param string file The filename for which to fire the event
122      *
123      * @return void
124      */
125     fireTeardown: function (file) {
126         var eventName = 'teardown_' + AJAX.hash(file);
127         $(document).triggerHandler(eventName);
128         if (this._debug) {
129             console.log(
130                 // no need to translate
131                 "Fired event " + eventName + " for file " + file
132             );
133         }
134     },
135     /**
136      * function to handle lock page mechanism
137      *
138      * @param event the event object
139      *
140      * @return void
141      */
142     lockPageHandler: function(event) {
143         //Don't lock on enter.
144         if (0 == event.charCode) {
145             return;
146         }
148         var lockId = $(this).data('lock-id');
149         if (typeof lockId === 'undefined') {
150             return;
151         }
152         /*
153          * @todo Fix Code mirror does not give correct full value (query)
154          * in textarea, it returns only the change in content.
155          */
156         var newHash = null;
157         if (event.data.value == 1) {
158             newHash = AJAX.hash($(this).val());
159         } else {
160             newHash = AJAX.hash($(this).is(":checked"));
161         }
162         var oldHash = $(this).data('val-hash');
163         // Set lock if old value != new value
164         // otherwise release lock
165         if (oldHash !== newHash) {
166             AJAX.lockedTargets[lockId] = true;
167         } else {
168             delete AJAX.lockedTargets[lockId];
169         }
170         // Show lock icon if locked targets is not empty.
171         // otherwise remove lock icon
172         if (!jQuery.isEmptyObject(AJAX.lockedTargets)) {
173             $('#lock_page_icon').html(PMA_getImage('s_lock.png',PMA_messages.strLockToolTip).toString());
174         } else {
175             $('#lock_page_icon').html('');
176         }
177     },
178     /**
179      * resets the lock
180      *
181      * @return void
182      */
183     resetLock: function() {
184         AJAX.lockedTargets = {};
185         $('#lock_page_icon').html('');
186     },
187     handleMenu: {
188         replace: function (content) {
189             $('#floating_menubar').html(content)
190                 // Remove duplicate wrapper
191                 // TODO: don't send it in the response
192                 .children().first().remove();
193             $('#topmenu').menuResizer(PMA_mainMenuResizerCallback);
194         }
195     },
196     /**
197      * Event handler for clicks on links and form submissions
198      *
199      * @param object e Event data
200      *
201      * @return void
202      */
203     requestHandler: function (event) {
204         // In some cases we don't want to handle the request here and either
205         // leave the browser deal with it natively (e.g: file download)
206         // or leave an existing ajax event handler present elsewhere deal with it
207         var href = $(this).attr('href');
208         if (typeof event != 'undefined' && (event.shiftKey || event.ctrlKey)) {
209             return true;
210         } else if ($(this).attr('target')) {
211             return true;
212         } else if ($(this).hasClass('ajax') || $(this).hasClass('disableAjax')) {
213             //reset the lockedTargets object, as specified AJAX operation has finished
214             AJAX.resetLock();
215             return true;
216         } else if (href && href.match(/^#/)) {
217             return true;
218         } else if (href && href.match(/^mailto/)) {
219             return true;
220         } else if ($(this).hasClass('ui-datepicker-next') ||
221             $(this).hasClass('ui-datepicker-prev')
222         ) {
223             return true;
224         }
226         if (typeof event != 'undefined') {
227             event.preventDefault();
228             event.stopImmediatePropagation();
229         }
231         //triggers a confirm dialog if:
232         //the user has performed some operations on loaded page
233         //the user clicks on some link, (won't trigger for buttons)
234         //the click event is not triggered by script
235         if (typeof event !== 'undefined' && event.type === 'click' &&
236             event.isTrigger !== true &&
237             !jQuery.isEmptyObject(AJAX.lockedTargets) &&
238             confirm(PMA_messages.strConfirmNavigation) === false
239         ) {
240             return false;
241         }
242         AJAX.resetLock();
243         var isLink = !! href || false;
244         var previousLinkAborted = false;
246         if (AJAX.active === true) {
247             // Cancel the old request if abortable, when the user requests
248             // something else. Otherwise silently bail out, as there is already
249             // a request well in progress.
250             if (AJAX.xhr) {
251                 //In case of a link request, attempt aborting
252                 AJAX.xhr.abort();
253                 if(AJAX.xhr.status === 0 && AJAX.xhr.statusText === 'abort') {
254                     //If aborted
255                     AJAX.$msgbox = PMA_ajaxShowMessage(PMA_messages.strAbortedRequest);
256                     AJAX.active = false;
257                     AJAX.xhr = null;
258                     previousLinkAborted = true;
259                 } else {
260                     //If can't abort
261                     return false;
262                 }
263             } else {
264                 //In case submitting a form, don't attempt aborting
265                 return false;
266             }
267         }
269         AJAX.source = $(this);
271         $('html, body').animate({scrollTop: 0}, 'fast');
273         var url = isLink ? href : $(this).attr('action');
274         var params = 'ajax_request=true&ajax_page_request=true';
275         if (! isLink) {
276             params += '&' + $(this).serialize();
277         }
278         if (! (history && history.pushState)) {
279             // Add a list of menu hashes that we have in the cache to the request
280             params += PMA_MicroHistory.menus.getRequestParam();
281         }
283         if (AJAX._debug) {
284             console.log("Loading: " + url); // no need to translate
285         }
287         if (isLink) {
288             AJAX.active = true;
289             AJAX.$msgbox = PMA_ajaxShowMessage();
290             //Save reference for the new link request
291             AJAX.xhr = $.get(url, params, AJAX.responseHandler);
292             if (history && history.pushState) {
293                 var state = {
294                     url : href
295                 };
296                 if (previousLinkAborted) {
297                     //hack: there is already an aborted entry on stack
298                     //so just modify the aborted one
299                     history.replaceState(state, null, href);
300                 } else {
301                     history.pushState(state, null, href);
302                 }
303             }
304         } else {
305             /**
306              * Manually fire the onsubmit event for the form, if any.
307              * The event was saved in the jQuery data object by an onload
308              * handler defined below. Workaround for bug #3583316
309              */
310             var onsubmit = $(this).data('onsubmit');
311             // Submit the request if there is no onsubmit handler
312             // or if it returns a value that evaluates to true
313             if (typeof onsubmit !== 'function' || onsubmit.apply(this, [event])) {
314                 AJAX.active = true;
315                 AJAX.$msgbox = PMA_ajaxShowMessage();
316                 $.post(url, params, AJAX.responseHandler);
317             }
318         }
319     },
320     /**
321      * Called after the request that was initiated by this.requestHandler()
322      * has completed successfully or with a caught error. For completely
323      * failed requests or requests with uncaught errors, see the .ajaxError
324      * handler at the bottom of this file.
325      *
326      * To refer to self use 'AJAX', instead of 'this' as this function
327      * is called in the jQuery context.
328      *
329      * @param object e Event data
330      *
331      * @return void
332      */
333     responseHandler: function (data) {
334         if (typeof data === 'undefined' || data === null) {
335             return;
336         }
337         if (typeof data.success != 'undefined' && data.success) {
338             $('html, body').animate({scrollTop: 0}, 'fast');
339             PMA_ajaxRemoveMessage(AJAX.$msgbox);
341             if (data._redirect) {
342                 PMA_ajaxShowMessage(data._redirect, false);
343                 AJAX.active = false;
344                 AJAX.xhr = null;
345                 return;
346             }
348             AJAX.scriptHandler.reset(function () {
349                 if (data._reloadNavigation) {
350                     PMA_reloadNavigation();
351                 }
352                 if (data._title) {
353                     $('title').replaceWith(data._title);
354                 }
355                 if (data._menu) {
356                     if (history && history.pushState) {
357                         var state = {
358                             url : data._selflink,
359                             menu : data._menu
360                         };
361                         history.replaceState(state, null);
362                         AJAX.handleMenu.replace(data._menu);
363                     } else {
364                         PMA_MicroHistory.menus.replace(data._menu);
365                         PMA_MicroHistory.menus.add(data._menuHash, data._menu);
366                     }
367                 } else if (data._menuHash) {
368                     if (! (history && history.pushState)) {
369                         PMA_MicroHistory.menus.replace(PMA_MicroHistory.menus.get(data._menuHash));
370                     }
371                 }
372                 if (data._disableNaviSettings) {
373                     PMA_disableNaviSettings();
374                 }
375                 else {
376                     PMA_ensureNaviSettings(data._selflink);
377                 }
379                 // Remove all containers that may have
380                 // been added outside of #page_content
381                 $('body').children()
382                     .not('#pma_navigation')
383                     .not('#floating_menubar')
384                     .not('#page_nav_icons')
385                     .not('#page_content')
386                     .not('#selflink')
387                     .not('#pma_header')
388                     .not('#pma_footer')
389                     .not('#pma_demo')
390                     .not('#pma_console_container')
391                     .not('#prefs_autoload')
392                     .remove();
393                 // Replace #page_content with new content
394                 if (data.message && data.message.length > 0) {
395                     $('#page_content').replaceWith(
396                         "<div id='page_content'>" + data.message + "</div>"
397                     );
398                     PMA_highlightSQL($('#page_content'));
399                     checkNumberOfFields();
400                 }
402                 if (data._selflink) {
403                     var source = data._selflink.split('?')[0];
404                     //Check for faulty links
405                     $selflink_replace = {
406                         "import.php": "tbl_sql.php",
407                         "tbl_chart.php": "sql.php",
408                         "tbl_gis_visualization.php": "sql.php"
409                     };
410                     if ($selflink_replace[source]) {
411                         var replacement = $selflink_replace[source];
412                         data._selflink = data._selflink.replace(source, replacement);
413                     }
414                     $('#selflink').find('> a').attr('href', data._selflink);
415                 }
416                 if (data._params) {
417                     PMA_commonParams.setAll(data._params);
418                 }
419                 if (data._scripts) {
420                     AJAX.scriptHandler.load(data._scripts);
421                 }
422                 if (data._selflink && data._scripts && data._menuHash && data._params) {
423                     if (! (history && history.pushState)) {
424                         PMA_MicroHistory.add(
425                             data._selflink,
426                             data._scripts,
427                             data._menuHash,
428                             data._params,
429                             AJAX.source.attr('rel')
430                         );
431                     }
432                 }
433                 if (data._displayMessage) {
434                     $('#page_content').prepend(data._displayMessage);
435                     PMA_highlightSQL($('#page_content'));
436                 }
438                 $('#pma_errors').remove();
440                 var msg = '';
441                 if(data._errSubmitMsg){
442                     msg = data._errSubmitMsg;
443                 }
444                 if (data._errors) {
445                     $('<div/>', {id : 'pma_errors'})
446                         .insertAfter('#selflink')
447                         .append(data._errors);
448                     // bind for php error reporting forms (bottom)
449                     $("#pma_ignore_errors_bottom").bind("click", function(e) {
450                         e.preventDefault();
451                         PMA_ignorePhpErrors();
452                     });
453                     $("#pma_ignore_all_errors_bottom").bind("click", function(e) {
454                         e.preventDefault();
455                         PMA_ignorePhpErrors(false);
456                     });
457                     // In case of 'sendErrorReport'='always'
458                     // submit the hidden error reporting form.
459                     if (data._sendErrorAlways == '1' &&
460                         data._stopErrorReportLoop != '1'
461                     ) {
462                         $("#pma_report_errors_form").submit();
463                         PMA_ajaxShowMessage(PMA_messages.phpErrorsBeingSubmitted, false);
464                         $('html, body').animate({scrollTop:$(document).height()}, 'slow');
465                     } else if (data._promptPhpErrors) {
466                         // otherwise just prompt user if it is set so.
467                         msg = msg + PMA_messages.phpErrorsFound;
468                         // scroll to bottom where all the errors are displayed.
469                         $('html, body').animate({scrollTop:$(document).height()}, 'slow');
470                     }
471                 }
472                 PMA_ajaxShowMessage(msg, false);
473                 // bind for php error reporting forms (popup)
474                 $("#pma_ignore_errors_popup").bind("click", function() {
475                     PMA_ignorePhpErrors();
476                 });
477                 $("#pma_ignore_all_errors_popup").bind("click", function() {
478                     PMA_ignorePhpErrors(false);
479                 });
481                 if (typeof AJAX._callback === 'function') {
482                     AJAX._callback.call();
483                 }
484                 AJAX._callback = function () {};
485             });
487         } else {
488             PMA_ajaxShowMessage(data.error, false);
489             AJAX.active = false;
490             AJAX.xhr = null;
491             PMA_handleRedirectAndReload(data);
492             if (data.fieldWithError) {
493                 $(':input.error').removeClass("error");
494                 $('#'+data.fieldWithError).addClass("error");
495             }
496         }
497     },
498     /**
499      * This object is in charge of downloading scripts,
500      * keeping track of what's downloaded and firing
501      * the onload event for them when the page is ready.
502      */
503     scriptHandler: {
504         /**
505          * @var array _scripts The list of files already downloaded
506          */
507         _scripts: [],
508         /**
509          * @var string _scriptsVersion version of phpMyAdmin from which the
510          *                             scripts have been loaded
511          */
512         _scriptsVersion: null,
513         /**
514          * @var array _scriptsToBeLoaded The list of files that
515          *                               need to be downloaded
516          */
517         _scriptsToBeLoaded: [],
518         /**
519          * @var array _scriptsToBeFired The list of files for which
520          *                              to fire the onload event
521          */
522         _scriptsToBeFired: [],
523         /**
524          * Records that a file has been downloaded
525          *
526          * @param string file The filename
527          * @param string fire Whether this file will be registering
528          *                    onload/teardown events
529          *
530          * @return self For chaining
531          */
532         add: function (file, fire) {
533             this._scripts.push(file);
534             if (fire) {
535                 // Record whether to fire any events for the file
536                 // This is necessary to correctly tear down the initial page
537                 this._scriptsToBeFired.push(file);
538             }
539             return this;
540         },
541         /**
542          * Download a list of js files in one request
543          *
544          * @param array files An array of filenames and flags
545          *
546          * @return void
547          */
548         load: function (files, callback) {
549             var self = this;
550             // Clear loaded scripts if they are from another version of phpMyAdmin.
551             // Depends on common params being set before loading scripts in responseHandler
552             if (self._scriptsVersion == null) {
553                 self._scriptsVersion = PMA_commonParams.get('PMA_VERSION');
554             } else if (self._scriptsVersion != PMA_commonParams.get('PMA_VERSION')) {
555                 self._scripts = [];
556                 self._scriptsVersion = PMA_commonParams.get('PMA_VERSION');
557             }
558             self._scriptsToBeLoaded = [];
559             self._scriptsToBeFired = [];
560             for (var i in files) {
561                 self._scriptsToBeLoaded.push(files[i].name);
562                 if (files[i].fire) {
563                     self._scriptsToBeFired.push(files[i].name);
564                 }
565             }
566             // Generate a request string
567             var request = [];
568             var needRequest = false;
569             for (var index in self._scriptsToBeLoaded) {
570                 var script = self._scriptsToBeLoaded[index];
571                 // Only for scripts that we don't already have
572                 if ($.inArray(script, self._scripts) == -1) {
573                     needRequest = true;
574                     this.add(script);
575                     request.push("scripts%5B%5D=" + script);
576                 }
577             }
578             request.push("call_done=1");
579             request.push("v=" + encodeURIComponent(PMA_commonParams.get('PMA_VERSION')));
580             // Download the composite js file, if necessary
581             if (needRequest) {
582                 this.appendScript("js/get_scripts.js.php?" + request.join("&"));
583             } else {
584                 self.done(callback);
585             }
586         },
587         /**
588          * Called whenever all files are loaded
589          *
590          * @return void
591          */
592         done: function (callback) {
593             if($.isFunction(callback)) {
594                 callback();
595             }
596             if (typeof ErrorReport !== 'undefined') {
597                 ErrorReport.wrap_global_functions();
598             }
599             for (var i in this._scriptsToBeFired) {
600                 AJAX.fireOnload(this._scriptsToBeFired[i]);
601             }
602             AJAX.active = false;
603         },
604         /**
605          * Appends a script element to the head to load the scripts
606          *
607          * @return void
608          */
609         appendScript: function (url) {
610             var head = document.head || document.getElementsByTagName('head')[0];
611             var script = document.createElement('script');
612             script.type = 'text/javascript';
613             script.src = url;
614             script.async = false;
615             head.appendChild(script);
616         },
617         /**
618          * Fires all the teardown event handlers for the current page
619          * and rebinds all forms and links to the request handler
620          *
621          * @param function callback The callback to call after resetting
622          *
623          * @return void
624          */
625         reset: function (callback) {
626             for (var i in this._scriptsToBeFired) {
627                 AJAX.fireTeardown(this._scriptsToBeFired[i]);
628             }
629             this._scriptsToBeFired = [];
630             /**
631              * Re-attach a generic event handler to clicks
632              * on pages and submissions of forms
633              */
634             $(document).off('click', 'a').on('click', 'a', AJAX.requestHandler);
635             $(document).off('submit', 'form').on('submit', 'form', AJAX.requestHandler);
636             if (! (history && history.pushState)) {
637                 PMA_MicroHistory.update();
638             }
639             callback();
640         }
641     }
645  * Here we register a function that will remove the onsubmit event from all
646  * forms that will be handled by the generic page loader. We then save this
647  * event handler in the "jQuery data", so that we can fire it up later in
648  * AJAX.requestHandler().
650  * See bug #3583316
651  */
652 AJAX.registerOnload('functions.js', function () {
653     // Registering the onload event for functions.js
654     // ensures that it will be fired for all pages
655     $('form').not('.ajax').not('.disableAjax').each(function () {
656         if ($(this).attr('onsubmit')) {
657             $(this).data('onsubmit', this.onsubmit).attr('onsubmit', '');
658         }
659     });
661     var $page_content = $('#page_content');
662     /**
663      * Workaround for passing submit button name,value on ajax form submit
664      * by appending hidden element with submit button name and value.
665      */
666     $page_content.on('click', 'form input[type=submit]', function() {
667         var buttonName = $(this).attr('name');
668         if (typeof buttonName === 'undefined') {
669             return;
670         }
671         $(this).closest('form').append($('<input/>', {
672             'type' : 'hidden',
673             'name' : buttonName,
674             'value': $(this).val()
675         }));
676     });
678     /**
679      * Attach event listener to events when user modify visible
680      * Input,Textarea and select fields to make changes in forms
681      */
682     $page_content.on(
683         'keyup change',
684         'form.lock-page textarea, ' +
685         'form.lock-page input[type="text"], ' +
686         'form.lock-page input[type="number"], ' +
687         'form.lock-page select',
688         {value:1},
689         AJAX.lockPageHandler
690     );
691     $page_content.on(
692         'change',
693         'form.lock-page input[type="checkbox"], ' +
694         'form.lock-page input[type="radio"]',
695         {value:2},
696         AJAX.lockPageHandler
697     );
698     /**
699      * Reset lock when lock-page form reset event is fired
700      * Note: reset does not bubble in all browser so attach to
701      * form directly.
702      */
703     $('form.lock-page').on('reset', function(event){
704         AJAX.resetLock();
705     });
709  * Page load event handler
710  */
711 $(function () {
712     var menuContent = $('<div></div>')
713         .append($('#serverinfo').clone())
714         .append($('#topmenucontainer').clone())
715         .html();
716     if (history && history.pushState) {
717         //set initial state reload
718         var initState = ('state' in window.history && window.history.state !== null);
719         var initURL = $('#selflink').find('> a').attr('href') || location.href;
720         var state = {
721             url : initURL,
722             menu : menuContent
723         };
724         history.replaceState(state, null);
726         $(window).on('popstate', function(event) {
727             var initPop = (! initState && location.href == initURL);
728             initState = true;
729             //check if popstate fired on first page itself
730             if (initPop) {
731                 return;
732             }
733             var state = event.originalEvent.state;
734             if (state && state.menu) {
735                 AJAX.$msgbox = PMA_ajaxShowMessage();
736                 var params = 'ajax_request=true&ajax_page_request=true';
737                 var url = state.url || location.href;
738                 $.get(url, params, AJAX.responseHandler);
739                 //TODO: Check if sometimes menu is not retrieved from server,
740                 // Not sure but it seems menu was missing only for printview which
741                 // been removed lately, so if it's right some dead menu checks/fallbacks
742                 // may need to be removed from this file and Header.class.php
743                 //AJAX.handleMenu.replace(event.originalEvent.state.menu);
744             }
745         });
746     } else {
747         // Fallback to microhistory mechanism
748         AJAX.scriptHandler
749             .load([{'name' : 'microhistory.js', 'fire' : 1}], function () {
750                 // The cache primer is set by the footer class
751                 if (PMA_MicroHistory.primer.url) {
752                     PMA_MicroHistory.menus.add(
753                         PMA_MicroHistory.primer.menuHash,
754                         menuContent
755                     );
756                 }
757                 $(function () {
758                     // Queue up this event twice to make sure that we get a copy
759                     // of the page after all other onload events have been fired
760                     if (PMA_MicroHistory.primer.url) {
761                         PMA_MicroHistory.add(
762                             PMA_MicroHistory.primer.url,
763                             PMA_MicroHistory.primer.scripts,
764                             PMA_MicroHistory.primer.menuHash
765                         );
766                     }
767                 });
768             });
769     }
773  * Attach a generic event handler to clicks
774  * on pages and submissions of forms
775  */
776 $(document).on('click', 'a', AJAX.requestHandler);
777 $(document).on('submit', 'form', AJAX.requestHandler);
780  * Gracefully handle fatal server errors
781  * (e.g: 500 - Internal server error)
782  */
783 $(document).ajaxError(function (event, request, settings) {
784     if (request.status !== 0) { // Don't handle aborted requests
785         var errorCode = PMA_sprintf(PMA_messages.strErrorCode, request.status);
786         var errorText = PMA_sprintf(PMA_messages.strErrorText, request.statusText);
787         PMA_ajaxShowMessage(
788             '<div class="error">' +
789             PMA_messages.strErrorProcessingRequest +
790             '<div>' + errorCode + '</div>' +
791             '<div>' + errorText + '</div>' +
792             '</div>',
793             false
794         );
795         AJAX.active = false;
796     }