Translated using Weblate (Slovenian)
[phpmyadmin.git] / js / ajax.js
blob13e388a58c5a186283d3d0c803a24804a03de58d
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._scripts) {
417                     AJAX.scriptHandler.load(data._scripts);
418                 }
419                 if (data._selflink && data._scripts && data._menuHash && data._params) {
420                     if (! (history && history.pushState)) {
421                         PMA_MicroHistory.add(
422                             data._selflink,
423                             data._scripts,
424                             data._menuHash,
425                             data._params,
426                             AJAX.source.attr('rel')
427                         );
428                     }
429                 }
430                 if (data._params) {
431                     PMA_commonParams.setAll(data._params);
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             if (parseInt(data.redirect_flag) == 1) {
492                 // add one more GET param to display session expiry msg
493                 window.location.href += '&session_expired=1';
494                 window.location.reload();
495             } else if (parseInt(data.reload_flag) == 1) {
496                 // remove the token param and reload
497                 window.location.href = window.location.href.replace(/&?token=[^&#]*/g, "");
498                 window.location.reload();
499             }
500             if (data.fieldWithError) {
501                 $(':input.error').removeClass("error");
502                 $('#'+data.fieldWithError).addClass("error");
503             }
504         }
505     },
506     /**
507      * This object is in charge of downloading scripts,
508      * keeping track of what's downloaded and firing
509      * the onload event for them when the page is ready.
510      */
511     scriptHandler: {
512         /**
513          * @var array _scripts The list of files already downloaded
514          */
515         _scripts: [],
516         /**
517          * @var array _scriptsToBeLoaded The list of files that
518          *                               need to be downloaded
519          */
520         _scriptsToBeLoaded: [],
521         /**
522          * @var array _scriptsToBeFired The list of files for which
523          *                              to fire the onload event
524          */
525         _scriptsToBeFired: [],
526         /**
527          * Records that a file has been downloaded
528          *
529          * @param string file The filename
530          * @param string fire Whether this file will be registering
531          *                    onload/teardown events
532          *
533          * @return self For chaining
534          */
535         add: function (file, fire) {
536             this._scripts.push(file);
537             if (fire) {
538                 // Record whether to fire any events for the file
539                 // This is necessary to correctly tear down the initial page
540                 this._scriptsToBeFired.push(file);
541             }
542             return this;
543         },
544         /**
545          * Download a list of js files in one request
546          *
547          * @param array files An array of filenames and flags
548          *
549          * @return void
550          */
551         load: function (files, callback) {
552             var self = this;
553             self._scriptsToBeLoaded = [];
554             self._scriptsToBeFired = [];
555             for (var i in files) {
556                 self._scriptsToBeLoaded.push(files[i].name);
557                 if (files[i].fire) {
558                     self._scriptsToBeFired.push(files[i].name);
559                 }
560             }
561             // Generate a request string
562             var request = [];
563             var needRequest = false;
564             for (var index in self._scriptsToBeLoaded) {
565                 var script = self._scriptsToBeLoaded[index];
566                 // Only for scripts that we don't already have
567                 if ($.inArray(script, self._scripts) == -1) {
568                     needRequest = true;
569                     this.add(script);
570                     request.push("scripts%5B%5D=" + script);
571                 }
572             }
573             request.push("call_done=1");
574             // Download the composite js file, if necessary
575             if (needRequest) {
576                 this.appendScript("js/get_scripts.js.php?" + request.join("&"));
577             } else {
578                 self.done(callback);
579             }
580         },
581         /**
582          * Called whenever all files are loaded
583          *
584          * @return void
585          */
586         done: function (callback) {
587             if($.isFunction(callback)) {
588                 callback();
589             }
590             if (typeof ErrorReport !== 'undefined') {
591                 ErrorReport.wrap_global_functions();
592             }
593             for (var i in this._scriptsToBeFired) {
594                 AJAX.fireOnload(this._scriptsToBeFired[i]);
595             }
596             AJAX.active = false;
597         },
598         /**
599          * Appends a script element to the head to load the scripts
600          *
601          * @return void
602          */
603         appendScript: function (url) {
604             var head = document.head || document.getElementsByTagName('head')[0];
605             var script = document.createElement('script');
606             script.type = 'text/javascript';
607             script.src = url;
608             script.async = false;
609             head.appendChild(script);
610         },
611         /**
612          * Fires all the teardown event handlers for the current page
613          * and rebinds all forms and links to the request handler
614          *
615          * @param function callback The callback to call after resetting
616          *
617          * @return void
618          */
619         reset: function (callback) {
620             for (var i in this._scriptsToBeFired) {
621                 AJAX.fireTeardown(this._scriptsToBeFired[i]);
622             }
623             this._scriptsToBeFired = [];
624             /**
625              * Re-attach a generic event handler to clicks
626              * on pages and submissions of forms
627              */
628             $(document).off('click', 'a').on('click', 'a', AJAX.requestHandler);
629             $(document).off('submit', 'form').on('submit', 'form', AJAX.requestHandler);
630             if (! (history && history.pushState)) {
631                 PMA_MicroHistory.update();
632             }
633             callback();
634         }
635     }
639  * Here we register a function that will remove the onsubmit event from all
640  * forms that will be handled by the generic page loader. We then save this
641  * event handler in the "jQuery data", so that we can fire it up later in
642  * AJAX.requestHandler().
644  * See bug #3583316
645  */
646 AJAX.registerOnload('functions.js', function () {
647     // Registering the onload event for functions.js
648     // ensures that it will be fired for all pages
649     $('form').not('.ajax').not('.disableAjax').each(function () {
650         if ($(this).attr('onsubmit')) {
651             $(this).data('onsubmit', this.onsubmit).attr('onsubmit', '');
652         }
653     });
655     var $page_content = $('#page_content');
656     /**
657      * Workaround for passing submit button name,value on ajax form submit
658      * by appending hidden element with submit button name and value.
659      */
660     $page_content.on('click', 'form input[type=submit]', function() {
661         var buttonName = $(this).attr('name');
662         if (typeof buttonName === 'undefined') {
663             return;
664         }
665         $(this).closest('form').append($('<input/>', {
666             'type' : 'hidden',
667             'name' : buttonName,
668             'value': $(this).val()
669         }));
670     });
672     /**
673      * Attach event listener to events when user modify visible
674      * Input,Textarea and select fields to make changes in forms
675      */
676     $page_content.on(
677         'keyup change',
678         'form.lock-page textarea, ' +
679         'form.lock-page input[type="text"], ' +
680         'form.lock-page input[type="number"], ' +
681         'form.lock-page select',
682         {value:1},
683         AJAX.lockPageHandler
684     );
685     $page_content.on(
686         'change',
687         'form.lock-page input[type="checkbox"], ' +
688         'form.lock-page input[type="radio"]',
689         {value:2},
690         AJAX.lockPageHandler
691     );
692     /**
693      * Reset lock when lock-page form reset event is fired
694      * Note: reset does not bubble in all browser so attach to
695      * form directly.
696      */
697     $('form.lock-page').on('reset', function(event){
698         AJAX.resetLock();
699     });
703  * Page load event handler
704  */
705 $(function () {
706     var menuContent = $('<div></div>')
707         .append($('#serverinfo').clone())
708         .append($('#topmenucontainer').clone())
709         .html();
710     if (history && history.pushState) {
711         //set initial state reload
712         var initState = ('state' in window.history && window.history.state !== null);
713         var initURL = $('#selflink').find('> a').attr('href') || location.href;
714         var state = {
715             url : initURL,
716             menu : menuContent
717         };
718         history.replaceState(state, null);
720         $(window).on('popstate', function(event) {
721             var initPop = (! initState && location.href == initURL);
722             initState = true;
723             //check if popstate fired on first page itself
724             if (initPop) {
725                 return;
726             }
727             var state = event.originalEvent.state;
728             if (state && state.menu) {
729                 AJAX.$msgbox = PMA_ajaxShowMessage();
730                 var params = 'ajax_request=true&ajax_page_request=true';
731                 var url = state.url || location.href;
732                 $.get(url, params, AJAX.responseHandler);
733                 //TODO: Check if sometimes menu is not retrieved from server,
734                 // Not sure but it seems menu was missing only for printview which
735                 // been removed lately, so if it's right some dead menu checks/fallbacks
736                 // may need to be removed from this file and Header.class.php
737                 //AJAX.handleMenu.replace(event.originalEvent.state.menu);
738             }
739         });
740     } else {
741         // Fallback to microhistory mechanism
742         AJAX.scriptHandler
743             .load([{'name' : 'microhistory.js', 'fire' : 1}], function () {
744                 // The cache primer is set by the footer class
745                 if (PMA_MicroHistory.primer.url) {
746                     PMA_MicroHistory.menus.add(
747                         PMA_MicroHistory.primer.menuHash,
748                         menuContent
749                     );
750                 }
751                 $(function () {
752                     // Queue up this event twice to make sure that we get a copy
753                     // of the page after all other onload events have been fired
754                     if (PMA_MicroHistory.primer.url) {
755                         PMA_MicroHistory.add(
756                             PMA_MicroHistory.primer.url,
757                             PMA_MicroHistory.primer.scripts,
758                             PMA_MicroHistory.primer.menuHash
759                         );
760                     }
761                 });
762             });
763     }
767  * Attach a generic event handler to clicks
768  * on pages and submissions of forms
769  */
770 $(document).on('click', 'a', AJAX.requestHandler);
771 $(document).on('submit', 'form', AJAX.requestHandler);
774  * Gracefully handle fatal server errors
775  * (e.g: 500 - Internal server error)
776  */
777 $(document).ajaxError(function (event, request, settings) {
778     if (request.status !== 0) { // Don't handle aborted requests
779         var errorCode = PMA_sprintf(PMA_messages.strErrorCode, request.status);
780         var errorText = PMA_sprintf(PMA_messages.strErrorText, request.statusText);
781         PMA_ajaxShowMessage(
782             '<div class="error">' +
783             PMA_messages.strErrorProcessingRequest +
784             '<div>' + errorCode + '</div>' +
785             '<div>' + errorText + '</div>' +
786             '</div>',
787             false
788         );
789         AJAX.active = false;
790     }