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