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