Translated using Weblate (Interlingua)
[phpmyadmin.git] / js / rte.js
blobca2f6d4d6c5aa93589dc16efbf69a27b274121a1
1 /* vim: set expandtab sw=4 ts=4 sts=4: */
2 /**
3  * JavaScript functionality for Routines, Triggers and Events.
4  *
5  * @package PhpMyadmin
6  */
7 /**
8  * @var RTE Contains all the JavaScript functionality
9  *          for Routines, Triggers and Events
10  */
11 var RTE = {
12     /**
13      * Construct for the object that provides the
14      * functionality for Routines, Triggers and Events
15      */
16     object: function (type) {
17         $.extend(this, RTE.COMMON);
18         this.editorType = type;
20         switch (type) {
21         case 'routine':
22             $.extend(this, RTE.ROUTINE);
23             break;
24         case 'trigger':
25             // nothing extra yet for triggers
26             break;
27         case 'event':
28             $.extend(this, RTE.EVENT);
29             break;
30         default:
31             break;
32         }
33     },
34     /**
35      * @var string param_template Template for a row in the routine editor
36      */
37     param_template: ''
40 /**
41  * @var RTE.COMMON a JavaScript namespace containing the functionality
42  *                 for Routines, Triggers and Events
43  *
44  *                 This namespace is extended by the functionality required
45  *                 to handle a specific item (a routine, trigger or event)
46  *                 in the relevant javascript files in this folder
47  */
48 RTE.COMMON = {
49     /**
50      * @var $ajaxDialog Query object containing the reference to the
51      *                  dialog that contains the editor
52      */
53     $ajaxDialog: null,
54     /**
55      * @var syntaxHiglighter Reference to the codemirror editor
56      */
57     syntaxHiglighter: null,
58     /**
59      * @var buttonOptions Object containing options for
60      *                    the jQueryUI dialog buttons
61      */
62     buttonOptions: {},
63     /**
64      * @var editorType Type of the editor
65      */
66     editorType: null,
67     /**
68      * Validate editor form fields.
69      */
70     validate: function () {
71         /**
72          * @var $elm a jQuery object containing the reference
73          *           to an element that is being validated
74          */
75         var $elm = null;
76         // Common validation. At the very least the name
77         // and the definition must be provided for an item
78         $elm = $('table.rte_table').last().find('input[name=item_name]');
79         if ($elm.val() === '') {
80             $elm.focus();
81             alert(PMA_messages.strFormEmpty);
82             return false;
83         }
84         $elm = $('table.rte_table').find('textarea[name=item_definition]');
85         if ($elm.val() === '') {
86             if (this.syntaxHiglighter !== null) {
87                 this.syntaxHiglighter.focus();
88             }
89             else {
90                 $('textarea[name=item_definition]').last().focus();
91             }
92             alert(PMA_messages.strFormEmpty);
93             return false;
94         }
95         // The validation has so far passed, so now
96         // we can validate item-specific fields.
97         return this.validateCustom();
98     }, // end validate()
99     /**
100      * Validate custom editor form fields.
101      * This function can be overridden by
102      * other files in this folder
103      */
104     validateCustom: function () {
105         return true;
106     }, // end validateCustom()
107     /**
108      * Execute some code after the ajax
109      * dialog for the editor is shown.
110      * This function can be overridden by
111      * other files in this folder
112      */
113     postDialogShow: function () {
114         // Nothing by default
115     }, // end postDialogShow()
117     exportDialog: function ($this) {
118         var $msg = PMA_ajaxShowMessage();
119         if ($this.hasClass('mult_submit')) {
120             var combined = {
121                 success: true,
122                 title: PMA_messages.strExport,
123                 message: '',
124                 error: ''
125             };
126             // export anchors of all selected rows
127             var export_anchors = $('input.checkall:checked').parents('tr').find('.export_anchor');
128             var count = export_anchors.length;
129             var returnCount = 0;
131             export_anchors.each(function () {
132                 $.get($(this).attr('href'), {'ajax_request': true}, function (data) {
133                     returnCount++;
134                     if (data.success === true) {
135                         combined.message += "\n" + data.message + "\n";
136                         if (returnCount == count) {
137                             showExport(combined);
138                         }
139                     } else {
140                         // complain even if one export is failing
141                         combined.success = false;
142                         combined.error += "\n" + data.error + "\n";
143                         if (returnCount == count) {
144                             showExport(combined);
145                         }
146                     }
147                 });
148             });
149         } else {
150             $.get($this.attr('href'), {'ajax_request': true}, showExport);
151         }
153         function showExport(data) {
154             if (data.success === true) {
155                 PMA_ajaxRemoveMessage($msg);
156                 /**
157                  * @var button_options Object containing options
158                  *                     for jQueryUI dialog buttons
159                  */
160                 var button_options = {};
161                 button_options[PMA_messages.strClose] = function () {
162                     $(this).dialog("close").remove();
163                 };
164                 /**
165                  * Display the dialog to the user
166                  */
167                 data.message = '<textarea cols="40" rows="15" style="width: 100%;">' + data.message + '</textarea>';
168                 var $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
169                     width: 500,
170                     buttons: button_options,
171                     title: data.title
172                 });
173                 // Attach syntax highlighted editor to export dialog
174                 /**
175                  * @var $elm jQuery object containing the reference
176                  *           to the Export textarea.
177                  */
178                 var $elm = $ajaxDialog.find('textarea');
179                 PMA_getSQLEditor($elm);
180             } else {
181                 PMA_ajaxShowMessage(data.error, false);
182             }
183         } // end showExport()
184     },  // end exportDialog()
185     editorDialog: function (is_new, $this) {
186         var that = this;
187         /**
188          * @var $edit_row jQuery object containing the reference to
189          *                the row of the the item being edited
190          *                from the list of items
191          */
192         var $edit_row = null;
193         if ($this.hasClass('edit_anchor')) {
194             // Remeber the row of the item being edited for later,
195             // so that if the edit is successful, we can replace the
196             // row with info about the modified item.
197             $edit_row = $this.parents('tr');
198         }
199         /**
200          * @var $msg jQuery object containing the reference to
201          *           the AJAX message shown to the user
202          */
203         var $msg = PMA_ajaxShowMessage();
204         $.get($this.attr('href'), {'ajax_request': true}, function (data) {
205             if (data.success === true) {
206                 // We have successfully fetched the editor form
207                 PMA_ajaxRemoveMessage($msg);
208                 // Now define the function that is called when
209                 // the user presses the "Go" button
210                 that.buttonOptions[PMA_messages.strGo] = function () {
211                     // Move the data from the codemirror editor back to the
212                     // textarea, where it can be used in the form submission.
213                     if (typeof CodeMirror != 'undefined') {
214                         that.syntaxHiglighter.save();
215                     }
216                     // Validate editor and submit request, if passed.
217                     if (that.validate()) {
218                         /**
219                          * @var data Form data to be sent in the AJAX request
220                          */
221                         var data = $('form.rte_form').last().serialize();
222                         $msg = PMA_ajaxShowMessage(
223                             PMA_messages.strProcessingRequest
224                         );
225                         var url = $('form.rte_form').last().attr('action');
226                         $.post(url, data, function (data) {
227                             if (data.success === true) {
228                                 // Item created successfully
229                                 PMA_ajaxRemoveMessage($msg);
230                                 PMA_slidingMessage(data.message);
231                                 that.$ajaxDialog.dialog('close');
232                                 // If we are in 'edit' mode, we must
233                                 // remove the reference to the old row.
234                                 if (mode === 'edit' && $edit_row !== null ) {
235                                     $edit_row.remove();
236                                 }
237                                 // Sometimes, like when moving a trigger from
238                                 // a table to another one, the new row should
239                                 // not be inserted into the list. In this case
240                                 // "data.insert" will be set to false.
241                                 if (data.insert) {
242                                     // Insert the new row at the correct
243                                     // location in the list of items
244                                     /**
245                                      * @var text Contains the name of an item from
246                                      *           the list that is used in comparisons
247                                      *           to find the correct location where
248                                      *           to insert a new row.
249                                      */
250                                     var text = '';
251                                     /**
252                                      * @var inserted Whether a new item has been
253                                      *               inserted in the list or not
254                                      */
255                                     var inserted = false;
256                                     $('table.data').find('tr').each(function () {
257                                         text = $(this)
258                                                 .children('td')
259                                                 .eq(0)
260                                                 .find('strong')
261                                                 .text()
262                                                 .toUpperCase();
263                                         text = $.trim(text);
264                                         if (text !== '' && text > data.name) {
265                                             $(this).before(data.new_row);
266                                             inserted = true;
267                                             return false;
268                                         }
269                                     });
270                                     if (! inserted) {
271                                         // If we didn't manage to insert the row yet,
272                                         // it must belong at the end of the list,
273                                         // so we insert it there.
274                                         $('table.data').append(data.new_row);
275                                     }
276                                     // Fade-in the new row
277                                     $('tr.ajaxInsert')
278                                         .show('slow')
279                                         .removeClass('ajaxInsert');
280                                 } else if ($('table.data').find('tr').has('td').length === 0) {
281                                     // If we are not supposed to insert the new row,
282                                     // we will now check if the table is empty and
283                                     // needs to be hidden. This will be the case if
284                                     // we were editing the only item in the list,
285                                     // which we removed and will not be inserting
286                                     // something else in its place.
287                                     $('table.data').hide("slow", function () {
288                                         $('#nothing2display').show("slow");
289                                     });
290                                 }
291                                 // Now we have inserted the row at the correct
292                                 // position, but surely at least some row classes
293                                 // are wrong now. So we will itirate throught
294                                 // all rows and assign correct classes to them
295                                 /**
296                                  * @var ct Count of processed rows
297                                  */
298                                 var ct = 0;
299                                 /**
300                                  * @var rowclass Class to be attached to the row
301                                  *               that is being processed
302                                  */
303                                 var rowclass = '';
304                                 $('table.data').find('tr').has('td').each(function () {
305                                     rowclass = (ct % 2 === 0) ? 'odd' : 'even';
306                                     $(this).removeClass().addClass(rowclass);
307                                     ct++;
308                                 });
309                                 // If this is the first item being added, remove
310                                 // the "No items" message and show the list.
311                                 if ($('table.data').find('tr').has('td').length > 0 &&
312                                     $('#nothing2display').is(':visible')
313                                     ) {
314                                     $('#nothing2display').hide("slow", function () {
315                                         $('table.data').show("slow");
316                                     });
317                                 }
318                                 PMA_reloadNavigation();
319                             } else {
320                                 PMA_ajaxShowMessage(data.error, false);
321                             }
322                         }); // end $.post()
323                     } // end "if (that.validate())"
324                 }; // end of function that handles the submission of the Editor
325                 that.buttonOptions[PMA_messages.strClose] = function () {
326                     $(this).dialog("close");
327                 };
328                 /**
329                  * Display the dialog to the user
330                  */
331                 that.$ajaxDialog = $('<div id="rteDialog">' + data.message + '</div>').dialog({
332                     width: 700,
333                     minWidth: 500,
334                     maxHeight: $(window).height(),
335                     buttons: that.buttonOptions,
336                     title: data.title,
337                     modal: true,
338                     open: function () {
339                         if ($('#rteDialog').parents('.ui-dialog').height() > $(window).height()) {
340                             $('#rteDialog').dialog("option", "height", $(window).height());
341                         }
342                         $(this).find('input[name=item_name]').focus();
343                         $(this).find('input.datefield').each(function () {
344                             PMA_addDatepicker($(this).css('width', '95%'), 'date');
345                         });
346                         $(this).find('input.datetimefield').each(function () {
347                             PMA_addDatepicker($(this).css('width', '95%'), 'datetime');
348                         });
349                         $.datepicker.initialized = false;
350                     },
351                     close: function () {
352                         $(this).remove();
353                     }
354                 });
355                 /**
356                  * @var mode Used to remeber whether the editor is in
357                  *           "Edit" or "Add" mode
358                  */
359                 var mode = 'add';
360                 if ($('input[name=editor_process_edit]').length > 0) {
361                     mode = 'edit';
362                 }
363                 // Attach syntax highlighted editor to the definition
364                 /**
365                  * @var elm jQuery object containing the reference to
366                  *                 the Definition textarea.
367                  */
368                 var $elm = $('textarea[name=item_definition]').last();
369                 var linterOptions = {};
370                 linterOptions[that.editorType + '_editor'] = true;
371                 that.syntaxHiglighter = PMA_getSQLEditor($elm, {}, null, linterOptions);
373                 // Execute item-specific code
374                 that.postDialogShow(data);
375             } else {
376                 PMA_ajaxShowMessage(data.error, false);
377             }
378         }); // end $.get()
379     },
381     dropDialog: function ($this) {
382         /**
383          * @var $curr_row Object containing reference to the current row
384          */
385         var $curr_row = $this.parents('tr');
386         /**
387          * @var question String containing the question to be asked for confirmation
388          */
389         var question = $('<div/>').text(
390             $curr_row.children('td').children('.drop_sql').html()
391         );
392         // We ask for confirmation first here, before submitting the ajax request
393         $this.PMA_confirm(question, $this.attr('href'), function (url) {
394             /**
395              * @var msg jQuery object containing the reference to
396              *          the AJAX message shown to the user
397              */
398             var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
399             $.post(url, {'is_js_confirmed': 1, 'ajax_request': true}, function (data) {
400                 if (data.success === true) {
401                     /**
402                      * @var $table Object containing reference
403                      *             to the main list of elements
404                      */
405                     var $table = $curr_row.parent();
406                     // Check how many rows will be left after we remove
407                     // the one that the user has requested us to remove
408                     if ($table.find('tr').length === 3) {
409                         // If there are two rows left, it means that they are
410                         // the header of the table and the rows that we are
411                         // about to remove, so after the removal there will be
412                         // nothing to show in the table, so we hide it.
413                         $table.hide("slow", function () {
414                             $(this).find('tr.even, tr.odd').remove();
415                             $('.withSelected').remove();
416                             $('#nothing2display').show("slow");
417                         });
418                     } else {
419                         $curr_row.hide("slow", function () {
420                             $(this).remove();
421                             // Now we have removed the row from the list, but maybe
422                             // some row classes are wrong now. So we will itirate
423                             // throught all rows and assign correct classes to them.
424                             /**
425                              * @var ct Count of processed rows
426                              */
427                             var ct = 0;
428                             /**
429                              * @var rowclass Class to be attached to the row
430                              *               that is being processed
431                              */
432                             var rowclass = '';
433                             $table.find('tr').has('td').each(function () {
434                                 rowclass = (ct % 2 === 1) ? 'odd' : 'even';
435                                 $(this).removeClass().addClass(rowclass);
436                                 ct++;
437                             });
438                         });
439                     }
440                     // Get rid of the "Loading" message
441                     PMA_ajaxRemoveMessage($msg);
442                     // Show the query that we just executed
443                     PMA_slidingMessage(data.sql_query);
444                     PMA_reloadNavigation();
445                 } else {
446                     PMA_ajaxShowMessage(data.error, false);
447                 }
448             }); // end $.post()
449         }); // end $.PMA_confirm()
450     },
452     dropMultipleDialog: function ($this) {
453         // We ask for confirmation here
454         $this.PMA_confirm(PMA_messages.strDropRTEitems, '', function (url) {
455             /**
456              * @var msg jQuery object containing the reference to
457              *          the AJAX message shown to the user
458              */
459             var $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
461             // drop anchors of all selected rows
462             var drop_anchors = $('input.checkall:checked').parents('tr').find('.drop_anchor');
463             var success = true;
464             var count = drop_anchors.length;
465             var returnCount = 0;
467             drop_anchors.each(function () {
468                 var $anchor = $(this);
469                 /**
470                  * @var $curr_row Object containing reference to the current row
471                  */
472                 var $curr_row = $anchor.parents('tr');
473                 $.post($anchor.attr('href'), {'is_js_confirmed': 1, 'ajax_request': true}, function (data) {
474                     returnCount++;
475                     if (data.success === true) {
476                         /**
477                          * @var $table Object containing reference
478                          *             to the main list of elements
479                          */
480                         var $table = $curr_row.parent();
481                         // Check how many rows will be left after we remove
482                         // the one that the user has requested us to remove
483                         if ($table.find('tr').length === 3) {
484                             // If there are two rows left, it means that they are
485                             // the header of the table and the rows that we are
486                             // about to remove, so after the removal there will be
487                             // nothing to show in the table, so we hide it.
488                             $table.hide("slow", function () {
489                                 $(this).find('tr.even, tr.odd').remove();
490                                 $('.withSelected').remove();
491                                 $('#nothing2display').show("slow");
492                             });
493                         } else {
494                             $curr_row.hide("fast", function () {
495                                 $(this).remove();
496                                 // Now we have removed the row from the list, but maybe
497                                 // some row classes are wrong now. So we will itirate
498                                 // throught all rows and assign correct classes to them.
499                                 /**
500                                  * @var ct Count of processed rows
501                                  */
502                                 var ct = 0;
503                                 /**
504                                  * @var rowclass Class to be attached to the row
505                                  *               that is being processed
506                                  */
507                                 var rowclass = '';
508                                 $table.find('tr').has('td').each(function () {
509                                     rowclass = (ct % 2 === 1) ? 'odd' : 'even';
510                                     $(this).removeClass().addClass(rowclass);
511                                     ct++;
512                                 });
513                             });
514                         }
515                         if (returnCount == count) {
516                             if (success) {
517                                 // Get rid of the "Loading" message
518                                 PMA_ajaxRemoveMessage($msg);
519                                 $('#rteListForm_checkall').prop({checked: false, indeterminate: false});
520                             }
521                             PMA_reloadNavigation();
522                         }
523                     } else {
524                         PMA_ajaxShowMessage(data.error, false);
525                         success = false;
526                         if (returnCount == count) {
527                             PMA_reloadNavigation();
528                         }
529                     }
530                 }); // end $.post()
531             }); // end drop_anchors.each()
532         }); // end $.PMA_confirm()
533     }
534 }; // end RTE namespace
537  * @var RTE.EVENT JavaScript functionality for events
538  */
539 RTE.EVENT = {
540     validateCustom: function () {
541         /**
542          * @var elm a jQuery object containing the reference
543          *          to an element that is being validated
544          */
545         var $elm = null;
546         if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'RECURRING') {
547             // The interval field must not be empty for recurring events
548             $elm = this.$ajaxDialog.find('input[name=item_interval_value]');
549             if ($elm.val() === '') {
550                 $elm.focus();
551                 alert(PMA_messages.strFormEmpty);
552                 return false;
553             }
554         } else {
555             // The execute_at field must not be empty for "once off" events
556             $elm = this.$ajaxDialog.find('input[name=item_execute_at]');
557             if ($elm.val() === '') {
558                 $elm.focus();
559                 alert(PMA_messages.strFormEmpty);
560                 return false;
561             }
562         }
563         return true;
564     }
568  * @var RTE.ROUTINE JavaScript functionality for routines
569  */
570 RTE.ROUTINE = {
571     /**
572      * Overriding the postDialogShow() function defined in common.js
573      *
574      * @param data JSON-encoded data from the ajax request
575      */
576     postDialogShow: function (data) {
577         // Cache the template for a parameter table row
578         RTE.param_template = data.param_template;
579         var that = this;
580         // Make adjustments in the dialog to make it AJAX compatible
581         $('td.routine_param_remove').show();
582         $('input[name=routine_removeparameter]').remove();
583         $('input[name=routine_addparameter]').css('width', '100%');
584         // Enable/disable the 'options' dropdowns for parameters as necessary
585         $('table.routine_params_table').last().find('th[colspan=2]').attr('colspan', '1');
586         $('table.routine_params_table').last().find('tr').has('td').each(function () {
587             that.setOptionsForParameter(
588                 $(this).find('select[name^=item_param_type]'),
589                 $(this).find('input[name^=item_param_length]'),
590                 $(this).find('select[name^=item_param_opts_text]'),
591                 $(this).find('select[name^=item_param_opts_num]')
592             );
593         });
594         // Enable/disable the 'options' dropdowns for
595         // function return value as necessary
596         this.setOptionsForParameter(
597             $('table.rte_table').last().find('select[name=item_returntype]'),
598             $('table.rte_table').last().find('input[name=item_returnlength]'),
599             $('table.rte_table').last().find('select[name=item_returnopts_text]'),
600             $('table.rte_table').last().find('select[name=item_returnopts_num]')
601         );
602         // Allow changing parameter order
603         $('.routine_params_table tbody').sortable({
604             containment: '.routine_params_table tbody',
605             handle: '.dragHandle',
606             stop: function(event, ui) {
607                 that.reindexParameters();
608             },
609         });
610     },
611     /**
612      * Reindexes the parameters after dropping a parameter or reordering parameters
613      */
614     reindexParameters: function () {
615         /**
616          * @var index Counter used for reindexing the input
617          *            fields in the routine parameters table
618          */
619         var index = 0;
620         $('table.routine_params_table tbody').find('tr').each(function () {
621             $(this).find(':input').each(function () {
622                 /**
623                  * @var inputname The value of the name attribute of
624                  *                the input field being reindexed
625                  */
626                 var inputname = $(this).attr('name');
627                 if (inputname.substr(0, 14) === 'item_param_dir') {
628                     $(this).attr('name', inputname.substr(0, 14) + '[' + index + ']');
629                 } else if (inputname.substr(0, 15) === 'item_param_name') {
630                     $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']');
631                 } else if (inputname.substr(0, 15) === 'item_param_type') {
632                     $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']');
633                 } else if (inputname.substr(0, 17) === 'item_param_length') {
634                     $(this).attr('name', inputname.substr(0, 17) + '[' + index + ']');
635                     $(this).attr('id', 'item_param_length_' + index);
636                 } else if (inputname.substr(0, 20) === 'item_param_opts_text') {
637                     $(this).attr('name', inputname.substr(0, 20) + '[' + index + ']');
638                 } else if (inputname.substr(0, 19) === 'item_param_opts_num') {
639                     $(this).attr('name', inputname.substr(0, 19) + '[' + index + ']');
640                 }
641             });
642             index++;
643         });
644     },
645     /**
646      * Overriding the validateCustom() function defined in common.js
647      */
648     validateCustom: function () {
649         /**
650          * @var isSuccess Stores the outcome of the validation
651          */
652         var isSuccess = true;
653         /**
654          * @var inputname The value of the "name" attribute for
655          *                the field that is being processed
656          */
657         var inputname = '';
658         this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () {
659             // Every parameter of a routine must have
660             // a non-empty direction, name and type
661             if (isSuccess) {
662                 $(this).find(':input').each(function () {
663                     inputname = $(this).attr('name');
664                     if (inputname.substr(0, 14) === 'item_param_dir' ||
665                         inputname.substr(0, 15) === 'item_param_name' ||
666                         inputname.substr(0, 15) === 'item_param_type') {
667                         if ($(this).val() === '') {
668                             $(this).focus();
669                             isSuccess = false;
670                             return false;
671                         }
672                     }
673                 });
674             } else {
675                 return false;
676             }
677         });
678         if (! isSuccess) {
679             alert(PMA_messages.strFormEmpty);
680             return false;
681         }
682         this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () {
683             // SET, ENUM, VARCHAR and VARBINARY fields must have length/values
684             var $inputtyp = $(this).find('select[name^=item_param_type]');
685             var $inputlen = $(this).find('input[name^=item_param_length]');
686             if ($inputtyp.length && $inputlen.length) {
687                 if (($inputtyp.val() === 'ENUM' || $inputtyp.val() === 'SET' || $inputtyp.val().substr(0, 3) === 'VAR') &&
688                     $inputlen.val() === ''
689                    ) {
690                     $inputlen.focus();
691                     isSuccess = false;
692                     return false;
693                 }
694             }
695         });
696         if (! isSuccess) {
697             alert(PMA_messages.strFormEmpty);
698             return false;
699         }
700         if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'FUNCTION') {
701             // The length/values of return variable for functions must
702             // be set, if the type is SET, ENUM, VARCHAR or VARBINARY.
703             var $returntyp = this.$ajaxDialog.find('select[name=item_returntype]');
704             var $returnlen = this.$ajaxDialog.find('input[name=item_returnlength]');
705             if (($returntyp.val() === 'ENUM' || $returntyp.val() === 'SET' || $returntyp.val().substr(0, 3) === 'VAR') &&
706                 $returnlen.val() === ''
707                 ) {
708                 $returnlen.focus();
709                 alert(PMA_messages.strFormEmpty);
710                 return false;
711             }
712         }
713         if ($('select[name=item_type]').find(':selected').val() === 'FUNCTION') {
714             // A function must contain a RETURN statement in its definition
715             if (this.$ajaxDialog.find('table.rte_table').find('textarea[name=item_definition]').val().toUpperCase().indexOf('RETURN') < 0) {
716                 this.syntaxHiglighter.focus();
717                 alert(PMA_messages.MissingReturn);
718                 return false;
719             }
720         }
721         return true;
722     },
723     /**
724      * Enable/disable the "options" dropdown and "length" input for
725      * parameters and the return variable in the routine editor
726      * as necessary.
727      *
728      * @param type a jQuery object containing the reference
729      *             to the "Type" dropdown box
730      * @param len  a jQuery object containing the reference
731      *             to the "Length" input box
732      * @param text a jQuery object containing the reference
733      *             to the dropdown box with options for
734      *             parameters of text type
735      * @param num  a jQuery object containing the reference
736      *             to the dropdown box with options for
737      *             parameters of numeric type
738      */
739     setOptionsForParameter: function ($type, $len, $text, $num) {
740         /**
741          * @var no_opts a jQuery object containing the reference
742          *              to an element to be displayed when no
743          *              options are available
744          */
745         var $no_opts = $text.parent().parent().find('.no_opts');
746         /**
747          * @var no_len a jQuery object containing the reference
748          *             to an element to be displayed when no
749          *             "length/values" field is available
750          */
751         var $no_len  = $len.parent().parent().find('.no_len');
753         // Process for parameter options
754         switch ($type.val()) {
755         case 'TINYINT':
756         case 'SMALLINT':
757         case 'MEDIUMINT':
758         case 'INT':
759         case 'BIGINT':
760         case 'DECIMAL':
761         case 'FLOAT':
762         case 'DOUBLE':
763         case 'REAL':
764             $text.parent().hide();
765             $num.parent().show();
766             $no_opts.hide();
767             break;
768         case 'TINYTEXT':
769         case 'TEXT':
770         case 'MEDIUMTEXT':
771         case 'LONGTEXT':
772         case 'CHAR':
773         case 'VARCHAR':
774         case 'SET':
775         case 'ENUM':
776             $text.parent().show();
777             $num.parent().hide();
778             $no_opts.hide();
779             break;
780         default:
781             $text.parent().hide();
782             $num.parent().hide();
783             $no_opts.show();
784             break;
785         }
786         // Process for parameter length
787         switch ($type.val()) {
788         case 'DATE':
789         case 'DATETIME':
790         case 'TIME':
791         case 'TINYBLOB':
792         case 'TINYTEXT':
793         case 'BLOB':
794         case 'TEXT':
795         case 'MEDIUMBLOB':
796         case 'MEDIUMTEXT':
797         case 'LONGBLOB':
798         case 'LONGTEXT':
799             $text.closest('tr').find('a:first').hide();
800             $len.parent().hide();
801             $no_len.show();
802             break;
803         default:
804             if ($type.val() == 'ENUM' || $type.val() == 'SET') {
805                 $text.closest('tr').find('a:first').show();
806             } else {
807                 $text.closest('tr').find('a:first').hide();
808             }
809             $len.parent().show();
810             $no_len.hide();
811             break;
812         }
813     },
814     executeDialog: function ($this) {
815         var that = this;
816         /**
817          * @var msg jQuery object containing the reference to
818          *          the AJAX message shown to the user
819          */
820         var $msg = PMA_ajaxShowMessage();
821         $.post($this.attr('href'), {'ajax_request': true}, function (data) {
822             if (data.success === true) {
823                 PMA_ajaxRemoveMessage($msg);
824                 // If 'data.dialog' is true we show a dialog with a form
825                 // to get the input parameters for routine, otherwise
826                 // we just show the results of the query
827                 if (data.dialog) {
828                     // Define the function that is called when
829                     // the user presses the "Go" button
830                     that.buttonOptions[PMA_messages.strGo] = function () {
831                         /**
832                          * @var data Form data to be sent in the AJAX request
833                          */
834                         var data = $('form.rte_form').last().serialize();
835                         $msg = PMA_ajaxShowMessage(
836                             PMA_messages.strProcessingRequest
837                         );
838                         $.post('db_routines.php', data, function (data) {
839                             if (data.success === true) {
840                                 // Routine executed successfully
841                                 PMA_ajaxRemoveMessage($msg);
842                                 PMA_slidingMessage(data.message);
843                                 $ajaxDialog.dialog('close');
844                             } else {
845                                 PMA_ajaxShowMessage(data.error, false);
846                             }
847                         });
848                     };
849                     that.buttonOptions[PMA_messages.strClose] = function () {
850                         $(this).dialog("close");
851                     };
852                     /**
853                      * Display the dialog to the user
854                      */
855                     var $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
856                         width: 650,
857                         buttons: that.buttonOptions,
858                         title: data.title,
859                         modal: true,
860                         close: function () {
861                             $(this).remove();
862                         }
863                     });
864                     $ajaxDialog.find('input[name^=params]').first().focus();
865                     /**
866                      * Attach the datepickers to the relevant form fields
867                      */
868                     $ajaxDialog.find('input.datefield, input.datetimefield').each(function () {
869                         PMA_addDatepicker($(this).css('width', '95%'));
870                     });
871                     /*
872                     * Define the function if the user presses enter
873                     */
874                     $('form.rte_form').on('keyup', function (event) {
875                         event.preventDefault();
876                         if (event.keyCode === 13) {
877                             /**
878                             * @var data Form data to be sent in the AJAX request
879                             */
880                             var data = $(this).serialize();
881                             $msg = PMA_ajaxShowMessage(
882                                 PMA_messages.strProcessingRequest
883                             );
884                             var url = $(this).attr('action');
885                             $.post(url, data, function (data) {
886                                 if (data.success === true) {
887                                     // Routine executed successfully
888                                     PMA_ajaxRemoveMessage($msg);
889                                     PMA_slidingMessage(data.message);
890                                     $('form.rte_form').off('keyup');
891                                     $ajaxDialog.remove();
892                                 } else {
893                                     PMA_ajaxShowMessage(data.error, false);
894                                 }
895                             });
896                         }
897                     });
898                 } else {
899                     // Routine executed successfully
900                     PMA_slidingMessage(data.message);
901                 }
902             } else {
903                 PMA_ajaxShowMessage(data.error, false);
904             }
905         }); // end $.post()
906     }
910  * Attach Ajax event handlers for the Routines, Triggers and Events editor
911  */
912 $(function () {
913     /**
914      * Attach Ajax event handlers for the Add/Edit functionality.
915      */
916     $(document).on('click', 'a.ajax.add_anchor, a.ajax.edit_anchor', function (event) {
917         event.preventDefault();
918         var type = $(this).attr('href').substr(0, $(this).attr('href').indexOf('?'));
919         if (type.indexOf('routine') != -1) {
920             type = 'routine';
921         } else if (type.indexOf('trigger') != -1) {
922             type = 'trigger';
923         } else if (type.indexOf('event') != -1) {
924             type = 'event';
925         } else {
926             type = '';
927         }
928         var dialog = new RTE.object(type);
929         dialog.editorDialog($(this).hasClass('add_anchor'), $(this));
930     }); // end $(document).on()
932     /**
933      * Attach Ajax event handlers for the Execute routine functionality
934      */
935     $(document).on('click', 'a.ajax.exec_anchor', function (event) {
936         event.preventDefault();
937         var dialog = new RTE.object('routine');
938         dialog.executeDialog($(this));
939     }); // end $(document).on()
941     /**
942      * Attach Ajax event handlers for Export of Routines, Triggers and Events
943      */
944     $(document).on('click', 'a.ajax.export_anchor', function (event) {
945         event.preventDefault();
946         var dialog = new RTE.object();
947         dialog.exportDialog($(this));
948     }); // end $(document).on()
950     $(document).on('click', '#rteListForm.ajax .mult_submit[value="export"]', function (event) {
951         event.preventDefault();
952         var dialog = new RTE.object();
953         dialog.exportDialog($(this));
954     }); // end $(document).on()
956     /**
957      * Attach Ajax event handlers for Drop functionality
958      * of Routines, Triggers and Events.
959      */
960     $(document).on('click', 'a.ajax.drop_anchor', function (event) {
961         event.preventDefault();
962         var dialog = new RTE.object();
963         dialog.dropDialog($(this));
964     }); // end $(document).on()
966     $(document).on('click', '#rteListForm.ajax .mult_submit[value="drop"]', function (event) {
967         event.preventDefault();
968         var dialog = new RTE.object();
969         dialog.dropMultipleDialog($(this));
970     }); // end $(document).on()
972     /**
973      * Attach Ajax event handlers for the "Change event/routine type"
974      * functionality in the events editor, so that the correct
975      * rows are shown in the editor when changing the event type
976      */
977     $(document).on('change', 'select[name=item_type]', function () {
978         $(this)
979         .closest('table')
980         .find('tr.recurring_event_row, tr.onetime_event_row, tr.routine_return_row, .routine_direction_cell')
981         .toggle();
982     }); // end $(document).on()
984     /**
985      * Attach Ajax event handlers for the "Change parameter type"
986      * functionality in the routines editor, so that the correct
987      * option/length fields, if any, are shown when changing
988      * a parameter type
989      */
990     $(document).on('change', 'select[name^=item_param_type]', function () {
991         /**
992          * @var row jQuery object containing the reference to
993          *          a row in the routine parameters table
994          */
995         var $row = $(this).parents('tr').first();
996         var rte = new RTE.object('routine');
997         rte.setOptionsForParameter(
998             $row.find('select[name^=item_param_type]'),
999             $row.find('input[name^=item_param_length]'),
1000             $row.find('select[name^=item_param_opts_text]'),
1001             $row.find('select[name^=item_param_opts_num]')
1002         );
1003     }); // end $(document).on()
1005     /**
1006      * Attach Ajax event handlers for the "Change the type of return
1007      * variable of function" functionality, so that the correct fields,
1008      * if any, are shown when changing the function return type type
1009      */
1010     $(document).on('change', 'select[name=item_returntype]', function () {
1011         var rte = new RTE.object('routine');
1012         var $table = $(this).closest('table.rte_table');
1013         rte.setOptionsForParameter(
1014             $table.find('select[name=item_returntype]'),
1015             $table.find('input[name=item_returnlength]'),
1016             $table.find('select[name=item_returnopts_text]'),
1017             $table.find('select[name=item_returnopts_num]')
1018         );
1019     }); // end $(document).on()
1021     /**
1022      * Attach Ajax event handlers for the "Add parameter to routine" functionality
1023      */
1024     $(document).on('click', 'input[name=routine_addparameter]', function (event) {
1025         event.preventDefault();
1026         /**
1027          * @var routine_params_table jQuery object containing the reference
1028          *                           to the routine parameters table
1029          */
1030         var $routine_params_table = $(this).closest('div.ui-dialog').find('.routine_params_table');
1031         /**
1032          * @var new_param_row A string containing the HTML code for the
1033          *                    new row for the routine parameters table
1034          */
1035         var new_param_row = RTE.param_template.replace(/%s/g, $routine_params_table.find('tr').length - 1);
1036         // Append the new row to the parameters table
1037         $routine_params_table.append(new_param_row);
1038         // Make sure that the row is correctly shown according to the type of routine
1039         if ($(this).closest('div.ui-dialog').find('table.rte_table select[name=item_type]').val() === 'FUNCTION') {
1040             $('tr.routine_return_row').show();
1041             $('td.routine_direction_cell').hide();
1042         }
1043         /**
1044          * @var newrow jQuery object containing the reference to the newly
1045          *             inserted row in the routine parameters table
1046          */
1047         var $newrow = $(this).closest('div.ui-dialog').find('table.routine_params_table').find('tr').has('td').last();
1048         // Enable/disable the 'options' dropdowns for parameters as necessary
1049         var rte = new RTE.object('routine');
1050         rte.setOptionsForParameter(
1051             $newrow.find('select[name^=item_param_type]'),
1052             $newrow.find('input[name^=item_param_length]'),
1053             $newrow.find('select[name^=item_param_opts_text]'),
1054             $newrow.find('select[name^=item_param_opts_num]')
1055         );
1056     }); // end $(document).on()
1058     /**
1059      * Attach Ajax event handlers for the
1060      * "Remove parameter from routine" functionality
1061      */
1062     $(document).on('click', 'a.routine_param_remove_anchor', function (event) {
1063         event.preventDefault();
1064         $(this).parent().parent().remove();
1065         // After removing a parameter, the indices of the name attributes in
1066         // the input fields lose the correct order and need to be reordered.
1067         RTE.ROUTINE.reindexParameters();
1068     }); // end $(document).on()
1069 }); // end of $()