Merge #15685 - Fix #15682 - Timestamp method not taking current time
[phpmyadmin.git] / js / tbl_structure.js
blob3f59c2452ac45f3fdace30319657378cee0adb10
1 /* vim: set expandtab sw=4 ts=4 sts=4: */
2 /**
3  * @fileoverview    functions used on the table structure page
4  * @name            Table Structure
5  *
6  * @requires    jQuery
7  * @requires    jQueryUI
8  * @required    js/functions.js
9  */
11 /**
12  * AJAX scripts for tbl_structure.php
13  *
14  * Actions ajaxified here:
15  * Drop Column
16  * Add Primary Key
17  * Drop Primary Key/Index
18  *
19  */
21 /**
22  * Reload fields table
23  */
24 function reloadFieldForm () {
25     $.post($('#fieldsForm').attr('action'), $('#fieldsForm').serialize() + PMA_commonParams.get('arg_separator') + 'ajax_request=true', function (form_data) {
26         var $temp_div = $('<div id=\'temp_div\'><div>').append(form_data.message);
27         $('#fieldsForm').replaceWith($temp_div.find('#fieldsForm'));
28         $('#addColumns').replaceWith($temp_div.find('#addColumns'));
29         $('#move_columns_dialog').find('ul').replaceWith($temp_div.find('#move_columns_dialog ul'));
30         $('#moveColumns').removeClass('move-active');
31     });
32     $('#page_content').show();
35 function checkFirst () {
36     if ($('select[name=after_field] option:selected').data('pos') === 'first') {
37         $('input[name=field_where]').val('first');
38     } else {
39         $('input[name=field_where]').val('after');
40     }
42 /**
43  * Unbind all event handlers before tearing down a page
44  */
45 AJAX.registerTeardown('tbl_structure.js', function () {
46     $(document).off('click', 'a.drop_column_anchor.ajax');
47     $(document).off('click', 'a.add_key.ajax');
48     $(document).off('click', '#move_columns_anchor');
49     $(document).off('click', '#printView');
50     $(document).off('submit', '.append_fields_form.ajax');
51     $('body').off('click', '#fieldsForm.ajax button[name="submit_mult"], #fieldsForm.ajax input[name="submit_mult"]');
52     $(document).off('click', 'a[name^=partition_action].ajax');
53     $(document).off('click', '#remove_partitioning.ajax');
54 });
56 AJAX.registerOnload('tbl_structure.js', function () {
57     // Re-initialize variables.
58     primary_indexes = [];
59     indexes = [];
60     fulltext_indexes = [];
61     spatial_indexes = [];
63     /**
64      *Ajax action for submitting the "Column Change" and "Add Column" form
65      */
66     $('.append_fields_form.ajax').off();
67     $(document).on('submit', '.append_fields_form.ajax', function (event) {
68         event.preventDefault();
69         /**
70          * @var    the_form    object referring to the export form
71          */
72         var $form = $(this);
73         var field_cnt = $form.find('input[name=orig_num_fields]').val();
76         function submitForm () {
77             $msg = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest);
78             $.post($form.attr('action'), $form.serialize() + PMA_commonParams.get('arg_separator') + 'do_save_data=1', function (data) {
79                 if ($('.sqlqueryresults').length !== 0) {
80                     $('.sqlqueryresults').remove();
81                 } else if ($('.error:not(.tab)').length !== 0) {
82                     $('.error:not(.tab)').remove();
83                 }
84                 if (typeof data.success !== 'undefined' && data.success === true) {
85                     $('#page_content')
86                         .empty()
87                         .append(data.message)
88                         .show();
89                     PMA_highlightSQL($('#page_content'));
90                     $('.result_query .notice').remove();
91                     reloadFieldForm();
92                     $form.remove();
93                     PMA_ajaxRemoveMessage($msg);
94                     PMA_init_slider();
95                     PMA_reloadNavigation();
96                 } else {
97                     PMA_ajaxShowMessage(data.error, false);
98                 }
99             }); // end $.post()
100         }
102         function checkIfConfirmRequired ($form, $field_cnt) {
103             var i = 0;
104             var id;
105             var elm;
106             var val;
107             var name_orig;
108             var elm_orig;
109             var val_orig;
110             var checkRequired = false;
111             for (i = 0; i < field_cnt; i++) {
112                 id = '#field_' + i + '_5';
113                 elm = $(id);
114                 val = elm.val();
116                 name_orig = 'input[name=field_collation_orig\\[' + i + '\\]]';
117                 elm_orig = $form.find(name_orig);
118                 val_orig = elm_orig.val();
120                 if (val && val_orig && val !== val_orig) {
121                     checkRequired = true;
122                     break;
123                 }
124             }
125             return checkRequired;
126         }
128         /*
129          * First validate the form; if there is a problem, avoid submitting it
130          *
131          * checkTableEditForm() needs a pure element and not a jQuery object,
132          * this is why we pass $form[0] as a parameter (the jQuery object
133          * is actually an array of DOM elements)
134          */
135         if (checkTableEditForm($form[0], field_cnt)) {
136             // OK, form passed validation step
138             PMA_prepareForAjaxRequest($form);
139             if (PMA_checkReservedWordColumns($form)) {
140                 // User wants to submit the form
142                 // If Collation is changed, Warn and Confirm
143                 if (checkIfConfirmRequired($form, field_cnt)) {
144                     var question = sprintf(
145                         PMA_messages.strChangeColumnCollation, 'https://wiki.phpmyadmin.net/pma/Garbled_data'
146                     );
147                     $form.PMA_confirm(question, $form.attr('action'), function (url) {
148                         submitForm();
149                     });
150                 } else {
151                     submitForm();
152                 }
153             }
154         }
155     }); // end change table button "do_save_data"
157     /**
158      * Attach Event Handler for 'Drop Column'
159      */
160     $(document).on('click', 'a.drop_column_anchor.ajax', function (event) {
161         event.preventDefault();
162         /**
163          * @var curr_table_name String containing the name of the current table
164          */
165         var curr_table_name = $(this).closest('form').find('input[name=table]').val();
166         /**
167          * @var curr_row    Object reference to the currently selected row (i.e. field in the table)
168          */
169         var $curr_row = $(this).parents('tr');
170         /**
171          * @var curr_column_name    String containing name of the field referred to by {@link curr_row}
172          */
173         var curr_column_name = $curr_row.children('th').children('label').text().trim();
174         curr_column_name = escapeHtml(curr_column_name);
175         /**
176          * @var $after_field_item    Corresponding entry in the 'After' field.
177          */
178         var $after_field_item = $('select[name=\'after_field\'] option[value=\'' + curr_column_name + '\']');
179         /**
180          * @var question    String containing the question to be asked for confirmation
181          */
182         var question = PMA_sprintf(PMA_messages.strDoYouReally, 'ALTER TABLE `' + escapeHtml(curr_table_name) + '` DROP `' + escapeHtml(curr_column_name) + '`;');
183         var $this_anchor = $(this);
184         $this_anchor.PMA_confirm(question, $this_anchor.attr('href'), function (url) {
185             var $msg = PMA_ajaxShowMessage(PMA_messages.strDroppingColumn, false);
186             var params = getJSConfirmCommonParam(this, $this_anchor.getPostData());
187             params += PMA_commonParams.get('arg_separator') + 'ajax_page_request=1';
188             $.post(url, params, function (data) {
189                 if (typeof data !== 'undefined' && data.success === true) {
190                     PMA_ajaxRemoveMessage($msg);
191                     if ($('.result_query').length) {
192                         $('.result_query').remove();
193                     }
194                     if (data.sql_query) {
195                         $('<div class="result_query"></div>')
196                             .html(data.sql_query)
197                             .prependTo('#structure_content');
198                         PMA_highlightSQL($('#page_content'));
199                     }
200                     // Adjust the row numbers
201                     for (var $row = $curr_row.next(); $row.length > 0; $row = $row.next()) {
202                         var new_val = parseInt($row.find('td:nth-child(2)').text(), 10) - 1;
203                         $row.find('td:nth-child(2)').text(new_val);
204                     }
205                     $after_field_item.remove();
206                     $curr_row.hide('medium').remove();
208                     // Remove the dropped column from select menu for 'after field'
209                     $('select[name=after_field]').find(
210                         '[value="' + curr_column_name + '"]'
211                     ).remove();
213                     // by default select the (new) last option to add new column
214                     // (in case last column is dropped)
215                     $('select[name=after_field] option:last').attr('selected','selected');
217                     // refresh table stats
218                     if (data.tableStat) {
219                         $('#tablestatistics').html(data.tableStat);
220                     }
221                     // refresh the list of indexes (comes from sql.php)
222                     $('.index_info').replaceWith(data.indexes_list);
223                     PMA_reloadNavigation();
224                 } else {
225                     PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest + ' : ' + data.error, false);
226                 }
227             }); // end $.post()
228         }); // end $.PMA_confirm()
229     }); // end of Drop Column Anchor action
231     /**
232      * Attach Event Handler for 'Print' link
233      */
234     $(document).on('click', '#printView', function (event) {
235         event.preventDefault();
237         // Take to preview mode
238         printPreview();
239     }); // end of Print View action
241     /**
242      * Ajax Event handler for adding keys
243      */
244     $(document).on('click', 'a.add_key.ajax', function (event) {
245         event.preventDefault();
247         var $this = $(this);
248         var curr_table_name = $this.closest('form').find('input[name=table]').val();
249         var curr_column_name = $this.parents('tr').children('th').children('label').text().trim();
251         var add_clause = '';
252         if ($this.is('.add_primary_key_anchor')) {
253             add_clause = 'ADD PRIMARY KEY';
254         } else if ($this.is('.add_index_anchor')) {
255             add_clause = 'ADD INDEX';
256         } else if ($this.is('.add_unique_anchor')) {
257             add_clause = 'ADD UNIQUE';
258         } else if ($this.is('.add_spatial_anchor')) {
259             add_clause = 'ADD SPATIAL';
260         } else if ($this.is('.add_fulltext_anchor')) {
261             add_clause = 'ADD FULLTEXT';
262         }
263         var question = PMA_sprintf(PMA_messages.strDoYouReally, 'ALTER TABLE `' +
264                 escapeHtml(curr_table_name) + '` ' + add_clause + '(`' + escapeHtml(curr_column_name) + '`);');
266         var $this_anchor = $(this);
268         $this_anchor.PMA_confirm(question, $this_anchor.attr('href'), function (url) {
269             PMA_ajaxShowMessage();
270             AJAX.source = $this;
272             var params = getJSConfirmCommonParam(this, $this_anchor.getPostData());
273             params += PMA_commonParams.get('arg_separator') + 'ajax_page_request=1';
274             $.post(url, params, AJAX.responseHandler);
275         }); // end $.PMA_confirm()
276     }); // end Add key
278     /**
279      * Inline move columns
280     **/
281     $(document).on('click', '#move_columns_anchor', function (e) {
282         e.preventDefault();
284         if ($(this).hasClass('move-active')) {
285             return;
286         }
288         /**
289          * @var    button_options  Object that stores the options passed to jQueryUI
290          *                          dialog
291          */
292         var button_options = {};
294         button_options[PMA_messages.strGo] = function (event) {
295             event.preventDefault();
296             var $msgbox = PMA_ajaxShowMessage();
297             var $this = $(this);
298             var $form = $this.find('form');
299             var serialized = $form.serialize();
301             // check if any columns were moved at all
302             if (serialized === $form.data('serialized-unmoved')) {
303                 PMA_ajaxRemoveMessage($msgbox);
304                 $this.dialog('close');
305                 return;
306             }
308             $.post($form.prop('action'), serialized + PMA_commonParams.get('arg_separator') + 'ajax_request=true', function (data) {
309                 if (data.success === false) {
310                     PMA_ajaxRemoveMessage($msgbox);
311                     $this
312                         .clone()
313                         .html(data.error)
314                         .dialog({
315                             title: $(this).prop('title'),
316                             height: 230,
317                             width: 900,
318                             modal: true,
319                             buttons: button_options_error
320                         }); // end dialog options
321                 } else {
322                     // sort the fields table
323                     var $fields_table = $('table#tablestructure tbody');
324                     // remove all existing rows and remember them
325                     var $rows = $fields_table.find('tr').remove();
326                     // loop through the correct order
327                     for (var i in data.columns) {
328                         var the_column = data.columns[i];
329                         var $the_row = $rows
330                             .find('input:checkbox[value=\'' + the_column + '\']')
331                             .closest('tr');
332                         // append the row for this column to the table
333                         $fields_table.append($the_row);
334                     }
335                     var $firstrow = $fields_table.find('tr').eq(0);
336                     // Adjust the row numbers and colors
337                     for (var $row = $firstrow; $row.length > 0; $row = $row.next()) {
338                         $row
339                             .find('td:nth-child(2)')
340                             .text($row.index() + 1)
341                             .end()
342                             .removeClass('odd even')
343                             .addClass($row.index() % 2 === 0 ? 'odd' : 'even');
344                     }
345                     PMA_ajaxShowMessage(data.message);
346                     $this.dialog('close');
347                 }
348             });
349         };
350         button_options[PMA_messages.strCancel] = function () {
351             $(this).dialog('close');
352         };
354         var button_options_error = {};
355         button_options_error[PMA_messages.strOK] = function () {
356             $(this).dialog('close').remove();
357         };
359         var columns = [];
361         $('#tablestructure').find('tbody tr').each(function () {
362             var col_name = $(this).find('input:checkbox').eq(0).val();
363             var hidden_input = $('<input/>')
364                 .prop({
365                     name: 'move_columns[]',
366                     type: 'hidden'
367                 })
368                 .val(col_name);
369             columns[columns.length] = $('<li/>')
370                 .addClass('placeholderDrag')
371                 .text(col_name)
372                 .append(hidden_input);
373         });
375         var col_list = $('#move_columns_dialog').find('ul')
376             .find('li').remove().end();
377         for (var i in columns) {
378             col_list.append(columns[i]);
379         }
380         col_list.sortable({
381             axis: 'y',
382             containment: $('#move_columns_dialog').find('div'),
383             tolerance: 'pointer'
384         }).disableSelection();
385         var $form = $('#move_columns_dialog').find('form');
386         $form.data('serialized-unmoved', $form.serialize());
388         $('#move_columns_dialog').dialog({
389             modal: true,
390             buttons: button_options,
391             open: function () {
392                 if ($('#move_columns_dialog').parents('.ui-dialog').height() > $(window).height()) {
393                     $('#move_columns_dialog').dialog('option', 'height', $(window).height());
394                 }
395             },
396             beforeClose: function () {
397                 $('#move_columns_anchor').removeClass('move-active');
398             }
399         });
400     });
402     /**
403      * Handles multi submits in table structure page such as change, browse, drop, primary etc.
404      */
405     $('body').on('click', '#fieldsForm.ajax button[name="submit_mult"], #fieldsForm.ajax input[name="submit_mult"]', function (e) {
406         e.preventDefault();
407         var $button = $(this);
408         var $form = $button.parents('form');
409         var argsep = PMA_commonParams.get('arg_separator');
410         var submitData = $form.serialize() + argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true' + argsep + 'submit_mult=' + $button.val();
411         PMA_ajaxShowMessage();
412         AJAX.source = $form;
413         $.post($form.attr('action'), submitData, AJAX.responseHandler);
414     });
416     /**
417      * Handles clicks on Action links in partition table
418      */
419     $(document).on('click', 'a[name^=partition_action].ajax', function (e) {
420         e.preventDefault();
421         var $link = $(this);
423         function submitPartitionAction (url) {
424             var params = 'ajax_request=true&ajax_page_request=true&' + $link.getPostData();
425             PMA_ajaxShowMessage();
426             AJAX.source = $link;
427             $.post(url, params, AJAX.responseHandler);
428         }
430         if ($link.is('#partition_action_DROP')) {
431             var question = PMA_messages.strDropPartitionWarning;
432             $link.PMA_confirm(question, $link.attr('href'), function (url) {
433                 submitPartitionAction(url);
434             });
435         } else if ($link.is('#partition_action_TRUNCATE')) {
436             var question = PMA_messages.strTruncatePartitionWarning;
437             $link.PMA_confirm(question, $link.attr('href'), function (url) {
438                 submitPartitionAction(url);
439             });
440         } else {
441             submitPartitionAction($link.attr('href'));
442         }
443     });
445     /**
446      * Handles remove partitioning
447      */
448     $(document).on('click', '#remove_partitioning.ajax', function (e) {
449         e.preventDefault();
450         var $link = $(this);
451         var question = PMA_messages.strRemovePartitioningWarning;
452         $link.PMA_confirm(question, $link.attr('href'), function (url) {
453             var params = getJSConfirmCommonParam({
454                 'ajax_request' : true,
455                 'ajax_page_request' : true
456             }, $link.getPostData());
457             PMA_ajaxShowMessage();
458             AJAX.source = $link;
459             $.post(url, params, AJAX.responseHandler);
460         });
461     });
463     $(document).on('change', 'select[name=after_field]', function () {
464         checkFirst();
465     });
468 /** Handler for "More" dropdown in structure table rows */
469 AJAX.registerOnload('tbl_structure.js', function () {
470     var windowwidth = $(window).width();
471     if (windowwidth > 768) {
472         if (! $('#fieldsForm').hasClass('HideStructureActions')) {
473             $('.table-structure-actions').width(function () {
474                 var width = 5;
475                 $(this).find('li').each(function () {
476                     width += $(this).outerWidth(true);
477                 });
478                 return width;
479             });
480         }
481     }
483     $('.jsresponsive').css('max-width', (windowwidth - 35) + 'px');
484     var tableRows = $('.central_columns');
485     $.each(tableRows, function (index, item) {
486         if ($(item).hasClass('add_button')) {
487             $(item).click(function () {
488                 $('input:checkbox').prop('checked', false);
489                 $('#checkbox_row_' + (index + 1)).prop('checked', true);
490                 $('button[value=add_to_central_columns]').click();
491             });
492         } else {
493             $(item).click(function () {
494                 $('input:checkbox').prop('checked', false);
495                 $('#checkbox_row_' + (index + 1)).prop('checked', true);
496                 $('button[value=remove_from_central_columns]').click();
497             });
498         }
499     });