tbl_structure.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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. */
  10. /**
  11. * AJAX scripts for tbl_structure.php
  12. *
  13. * Actions ajaxified here:
  14. * Drop Column
  15. * Add Primary Key
  16. * Drop Primary Key/Index
  17. *
  18. */
  19. /**
  20. * This function returns the horizontal space available for the menu in pixels.
  21. * To calculate this value we start we the width of the main panel, then we
  22. * substract the margin of the page content, then we substract any cellspacing
  23. * that the table may have (original theme only) and finally we substract the
  24. * width of all columns of the table except for the last one (which is where
  25. * the menu will go). What we should end up with is the distance between the
  26. * start of the last column on the table and the edge of the page, again this
  27. * is the space available for the menu.
  28. *
  29. * In the case where the table cell where the menu will be displayed is already
  30. * off-screen (the table is wider than the page), a negative value will be returned,
  31. * but this will be treated as a zero by the menuResizer plugin.
  32. *
  33. * @return int
  34. */
  35. function PMA_tbl_structure_menu_resizer_callback() {
  36. var pagewidth = $('body').width();
  37. var $page = $('#page_content');
  38. pagewidth -= $page.outerWidth(true) - $page.outerWidth();
  39. var columnsWidth = 0;
  40. var $columns = $('#tablestructure').find('tr:eq(1)').find('td,th');
  41. $columns.not(':last').each(function () {
  42. columnsWidth += $(this).outerWidth(true);
  43. });
  44. var totalCellSpacing = $('#tablestructure').width();
  45. $columns.each(function () {
  46. totalCellSpacing -= $(this).outerWidth(true);
  47. });
  48. return pagewidth - columnsWidth - totalCellSpacing - 15; // 15px extra margin
  49. }
  50. /**
  51. * Reload fields table
  52. */
  53. function reloadFieldForm() {
  54. $.post($("#fieldsForm").attr('action'), $("#fieldsForm").serialize() + "&ajax_request=true", function (form_data) {
  55. var $temp_div = $("<div id='temp_div'><div>").append(form_data.message);
  56. $("#fieldsForm").replaceWith($temp_div.find("#fieldsForm"));
  57. $("#addColumns").replaceWith($temp_div.find("#addColumns"));
  58. $('#move_columns_dialog ul').replaceWith($temp_div.find("#move_columns_dialog ul"));
  59. $("#moveColumns").removeClass("move-active");
  60. /* reinitialise the more options in table */
  61. $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
  62. });
  63. $('#page_content').show();
  64. }
  65. /**
  66. * Unbind all event handlers before tearing down a page
  67. */
  68. AJAX.registerTeardown('tbl_structure.js', function () {
  69. $("a.change_column_anchor.ajax").die('click');
  70. $("button.change_columns_anchor.ajax, input.change_columns_anchor.ajax").die('click');
  71. $("a.drop_column_anchor.ajax").die('click');
  72. $("a.add_primary_key_anchor.ajax").die('click');
  73. $("a.add_index_anchor.ajax").die('click');
  74. $("a.add_unique_anchor.ajax").die('click');
  75. $("#move_columns_anchor").die('click');
  76. $(".append_fields_form.ajax").unbind('submit');
  77. });
  78. AJAX.registerOnload('tbl_structure.js', function () {
  79. /**
  80. *Ajax action for submitting the "Column Change" and "Add Column" form
  81. */
  82. $(".append_fields_form.ajax").die().live('submit', function (event) {
  83. event.preventDefault();
  84. /**
  85. * @var the_form object referring to the export form
  86. */
  87. var $form = $(this);
  88. /*
  89. * First validate the form; if there is a problem, avoid submitting it
  90. *
  91. * checkTableEditForm() needs a pure element and not a jQuery object,
  92. * this is why we pass $form[0] as a parameter (the jQuery object
  93. * is actually an array of DOM elements)
  94. */
  95. if (checkTableEditForm($form[0], $form.find('input[name=orig_num_fields]').val())) {
  96. // OK, form passed validation step
  97. PMA_prepareForAjaxRequest($form);
  98. //User wants to submit the form
  99. $msg = PMA_ajaxShowMessage();
  100. $.post($form.attr('action'), $form.serialize() + '&do_save_data=1', function (data) {
  101. if ($("#sqlqueryresults").length !== 0) {
  102. $("#sqlqueryresults").remove();
  103. } else if ($(".error:not(.tab)").length !== 0) {
  104. $(".error:not(.tab)").remove();
  105. }
  106. if (data.success === true) {
  107. $("#page_content")
  108. .empty()
  109. .append(data.message)
  110. .append(data.sql_query)
  111. .show();
  112. PMA_highlightSQL($('#page_content'));
  113. $("#result_query .notice").remove();
  114. reloadFieldForm();
  115. $form.remove();
  116. PMA_ajaxRemoveMessage($msg);
  117. PMA_init_slider();
  118. PMA_reloadNavigation();
  119. } else {
  120. PMA_ajaxShowMessage(data.error, false);
  121. }
  122. }); // end $.post()
  123. }
  124. }); // end change table button "do_save_data"
  125. /**
  126. * Attach Event Handler for 'Change Column'
  127. */
  128. $("a.change_column_anchor.ajax").live('click', function (event) {
  129. event.preventDefault();
  130. var $msg = PMA_ajaxShowMessage();
  131. $('#page_content').hide();
  132. $.get($(this).attr('href'), {'ajax_request': true}, function (data) {
  133. PMA_ajaxRemoveMessage($msg);
  134. if (data.success) {
  135. $('<div id="change_column_dialog" class="margin"></div>')
  136. .html(data.message)
  137. .insertBefore('#page_content');
  138. PMA_highlightSQL($('#page_content'));
  139. PMA_showHints();
  140. PMA_verifyColumnsProperties();
  141. } else {
  142. PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest + " : " + data.error, false);
  143. }
  144. });
  145. });
  146. /**
  147. * Attach Event Handler for 'Change multiple columns'
  148. */
  149. $("button.change_columns_anchor.ajax, input.change_columns_anchor.ajax").live('click', function (event) {
  150. event.preventDefault();
  151. var $msg = PMA_ajaxShowMessage();
  152. $('#page_content').hide();
  153. var $form = $(this).closest('form');
  154. var params = $form.serialize() + "&ajax_request=true&submit_mult=change";
  155. $.post($form.prop("action"), params, function (data) {
  156. PMA_ajaxRemoveMessage($msg);
  157. if (data.success) {
  158. $('#page_content')
  159. .empty()
  160. .append(
  161. $('<div id="change_column_dialog"></div>')
  162. .html(data.message)
  163. )
  164. .show();
  165. PMA_highlightSQL($('#page_content'));
  166. PMA_showHints();
  167. PMA_verifyColumnsProperties();
  168. } else {
  169. $('#page_content').show();
  170. PMA_ajaxShowMessage(data.error);
  171. }
  172. });
  173. });
  174. /**
  175. * Attach Event Handler for 'Drop Column'
  176. */
  177. $("a.drop_column_anchor.ajax").live('click', function (event) {
  178. event.preventDefault();
  179. /**
  180. * @var curr_table_name String containing the name of the current table
  181. */
  182. var curr_table_name = $(this).closest('form').find('input[name=table]').val();
  183. /**
  184. * @var curr_row Object reference to the currently selected row (i.e. field in the table)
  185. */
  186. var $curr_row = $(this).parents('tr');
  187. /**
  188. * @var curr_column_name String containing name of the field referred to by {@link curr_row}
  189. */
  190. var curr_column_name = $curr_row.children('th').children('label').text();
  191. curr_column_name = escapeHtml(curr_column_name);
  192. /**
  193. * @var $after_field_item Corresponding entry in the 'After' field.
  194. */
  195. var $after_field_item = $("select[name='after_field'] option[value='" + curr_column_name + "']");
  196. /**
  197. * @var question String containing the question to be asked for confirmation
  198. */
  199. var question = $.sprintf(PMA_messages.strDoYouReally, 'ALTER TABLE `' + escapeHtml(curr_table_name) + '` DROP `' + escapeHtml(curr_column_name) + '`;');
  200. $(this).PMA_confirm(question, $(this).attr('href'), function (url) {
  201. var $msg = PMA_ajaxShowMessage(PMA_messages.strDroppingColumn, false);
  202. $.get(url, {'is_js_confirmed' : 1, 'ajax_request' : true, 'ajax_page_request' : true}, function (data) {
  203. if (data.success === true) {
  204. PMA_ajaxRemoveMessage($msg);
  205. if ($('#result_query').length) {
  206. $('#result_query').remove();
  207. }
  208. if (data.sql_query) {
  209. $('<div id="result_query"></div>')
  210. .html(data.sql_query)
  211. .prependTo('#page_content');
  212. PMA_highlightSQL($('#page_content'));
  213. }
  214. toggleRowColors($curr_row.next());
  215. // Adjust the row numbers
  216. for (var $row = $curr_row.next(); $row.length > 0; $row = $row.next()) {
  217. var new_val = parseInt($row.find('td:nth-child(2)').text(), 10) - 1;
  218. $row.find('td:nth-child(2)').text(new_val);
  219. }
  220. $after_field_item.remove();
  221. $curr_row.hide("medium").remove();
  222. //refresh table stats
  223. if (data.tableStat) {
  224. $('#tablestatistics').html(data.tableStat);
  225. }
  226. // refresh the list of indexes (comes from sql.php)
  227. $('.index_info').replaceWith(data.indexes_list);
  228. PMA_reloadNavigation();
  229. } else {
  230. PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest + " : " + data.error, false);
  231. }
  232. }); // end $.get()
  233. }); // end $.PMA_confirm()
  234. }); //end of Drop Column Anchor action
  235. /**
  236. * Ajax Event handler for 'Add Primary Key'
  237. */
  238. $("a.add_primary_key_anchor.ajax").live('click', function (event) {
  239. event.preventDefault();
  240. /**
  241. * @var curr_table_name String containing the name of the current table
  242. */
  243. var curr_table_name = $(this).closest('form').find('input[name=table]').val();
  244. /**
  245. * @var curr_column_name String containing name of the field referred to by {@link curr_row}
  246. */
  247. var curr_column_name = $(this).parents('tr').children('th').children('label').text();
  248. /**
  249. * @var question String containing the question to be asked for confirmation
  250. */
  251. var question = $.sprintf(PMA_messages.strDoYouReally, 'ALTER TABLE `' + escapeHtml(curr_table_name) + '` ADD PRIMARY KEY(`' + escapeHtml(curr_column_name) + '`);');
  252. $(this).PMA_confirm(question, $(this).attr('href'), function (url) {
  253. var $msg = PMA_ajaxShowMessage(PMA_messages.strAddingPrimaryKey, false);
  254. $.get(url
  255. , {'is_js_confirmed' : 1, 'ajax_request' : true, 'index_change' : true}
  256. , function (data) {
  257. if (data.success === true) {
  258. PMA_ajaxRemoveMessage($msg);
  259. $(this).remove();
  260. if (typeof data.reload != 'undefined') {
  261. PMA_commonActions.refreshMain(false, function () {
  262. if ($('#result_query').length) {
  263. $('#result_query').remove();
  264. }
  265. if (data.sql_query) {
  266. $('<div id="result_query"></div>')
  267. .html(data.sql_query)
  268. .prependTo('#page_content');
  269. PMA_highlightSQL($('#page_content'));
  270. }
  271. });
  272. PMA_reloadNavigation();
  273. }
  274. if (data.indexes_list) {
  275. $('.index_info').replaceWith(data.indexes_list);
  276. }
  277. } else {
  278. PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest + " : " + data.error, false);
  279. }
  280. }); // end $.get()
  281. }); // end $.PMA_confirm()
  282. }); //end Add Primary Key
  283. /**
  284. * Ajax Event handler for 'Add Index'
  285. */
  286. $("a.add_index_anchor.ajax").live('click', function (event) {
  287. event.preventDefault();
  288. /**
  289. * @var curr_table_name String containing the name of the current table
  290. */
  291. var curr_table_name = $(this).closest('form').find('input[name=table]').val();
  292. /**
  293. * @var curr_column_name String containing name of the field referred to by {@link curr_row}
  294. */
  295. var curr_column_name = $(this).parents('tr').children('th').children('label').text();
  296. /**
  297. * @var question String containing the question to be asked for confirmation
  298. */
  299. var question = $.sprintf(PMA_messages.strDoYouReally, 'ALTER TABLE `' + escapeHtml(curr_table_name) + '` ADD INDEX(`' + escapeHtml(curr_column_name) + '`);');
  300. $(this).PMA_confirm(question, $(this).attr('href'), function (url) {
  301. var $msg = PMA_ajaxShowMessage(PMA_messages.strAddingIndex, false);
  302. $.get(url
  303. , {'is_js_confirmed' : 1, 'ajax_request' : true, 'index_change' : true}
  304. , function (data) {
  305. if (data.success === true) {
  306. PMA_ajaxRemoveMessage($msg);
  307. if ($('#result_query').length) {
  308. $('#result_query').remove();
  309. }
  310. if (data.sql_query) {
  311. $('<div id="result_query"></div>')
  312. .html(data.sql_query)
  313. .prependTo('#page_content');
  314. PMA_highlightSQL($('#page_content'));
  315. }
  316. if (data.indexes_list) {
  317. $('.index_info').replaceWith(data.indexes_list);
  318. }
  319. PMA_reloadNavigation();
  320. } else {
  321. PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest + " : " + data.error, false);
  322. }
  323. }); // end $.get()
  324. }); // end $.PMA_confirm()
  325. }); //end Add Index
  326. /**
  327. * Ajax Event handler for 'Add Unique'
  328. */
  329. $("a.add_unique_anchor.ajax").live('click', function (event) {
  330. event.preventDefault();
  331. /**
  332. * @var curr_table_name String containing the name of the current table
  333. */
  334. var curr_table_name = $(this).closest('form').find('input[name=table]').val();
  335. /**
  336. * @var curr_column_name String containing name of the field referred to by {@link curr_row}
  337. */
  338. var curr_column_name = $(this).parents('tr').children('th').children('label').text();
  339. /**
  340. * @var question String containing the question to be asked for confirmation
  341. */
  342. var question = $.sprintf(PMA_messages.strDoYouReally, 'ALTER TABLE `' + escapeHtml(curr_table_name) + '` ADD UNIQUE(`' + escapeHtml(curr_column_name) + '`);');
  343. $(this).PMA_confirm(question, $(this).attr('href'), function (url) {
  344. var $msg = PMA_ajaxShowMessage(PMA_messages.strAddingUnique, false);
  345. $.get(url
  346. , {'is_js_confirmed' : 1, 'ajax_request' : true, 'index_change' : true}
  347. , function (data) {
  348. if (data.success === true) {
  349. PMA_ajaxRemoveMessage($msg);
  350. if ($('#result_query').length) {
  351. $('#result_query').remove();
  352. }
  353. if (data.sql_query) {
  354. $('<div id="result_query"></div>')
  355. .html(data.sql_query)
  356. .prependTo('#page_content');
  357. PMA_highlightSQL($('#page_content'));
  358. }
  359. if (data.indexes_list) {
  360. $('.index_info').replaceWith(data.indexes_list);
  361. }
  362. PMA_reloadNavigation();
  363. } else {
  364. PMA_ajaxShowMessage(PMA_messages.strErrorProcessingRequest + " : " + data.error, false);
  365. }
  366. }); // end $.get()
  367. }); // end $.PMA_confirm()
  368. }); //end Add Unique
  369. /**
  370. * Inline move columns
  371. **/
  372. $("#move_columns_anchor").live('click', function (e) {
  373. e.preventDefault();
  374. if ($(this).hasClass("move-active")) {
  375. return;
  376. }
  377. /**
  378. * @var button_options Object that stores the options passed to jQueryUI
  379. * dialog
  380. */
  381. var button_options = {};
  382. button_options[PMA_messages.strGo] = function (event) {
  383. event.preventDefault();
  384. var $msgbox = PMA_ajaxShowMessage();
  385. var $this = $(this);
  386. var $form = $this.find("form");
  387. var serialized = $form.serialize();
  388. // check if any columns were moved at all
  389. if (serialized == $form.data("serialized-unmoved")) {
  390. PMA_ajaxRemoveMessage($msgbox);
  391. $this.dialog('close');
  392. return;
  393. }
  394. $.post($form.prop("action"), serialized + "&ajax_request=true", function (data) {
  395. if (data.success === false) {
  396. PMA_ajaxRemoveMessage($msgbox);
  397. $this
  398. .clone()
  399. .html(data.error)
  400. .dialog({
  401. title: $(this).prop("title"),
  402. height: 230,
  403. width: 900,
  404. modal: true,
  405. buttons: button_options_error
  406. }); // end dialog options
  407. } else {
  408. $('#fieldsForm ul.table-structure-actions').menuResizer('destroy');
  409. // sort the fields table
  410. var $fields_table = $("table#tablestructure tbody");
  411. // remove all existing rows and remember them
  412. var $rows = $fields_table.find("tr").remove();
  413. // loop through the correct order
  414. for (var i in data.columns) {
  415. var the_column = data.columns[i];
  416. var $the_row = $rows
  417. .find("input:checkbox[value=" + the_column + "]")
  418. .closest("tr");
  419. // append the row for this column to the table
  420. $fields_table.append($the_row);
  421. }
  422. var $firstrow = $fields_table.find("tr").eq(0);
  423. // Adjust the row numbers and colors
  424. for (var $row = $firstrow; $row.length > 0; $row = $row.next()) {
  425. $row
  426. .find('td:nth-child(2)')
  427. .text($row.index() + 1)
  428. .end()
  429. .removeClass("odd even")
  430. .addClass($row.index() % 2 === 0 ? "odd" : "even");
  431. }
  432. PMA_ajaxShowMessage(data.message);
  433. $this.dialog('close');
  434. $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
  435. }
  436. });
  437. };
  438. button_options[PMA_messages.strCancel] = function () {
  439. $(this).dialog('close');
  440. };
  441. var button_options_error = {};
  442. button_options_error[PMA_messages.strOK] = function () {
  443. $(this).dialog('close').remove();
  444. };
  445. var columns = [];
  446. $("#tablestructure tbody tr").each(function () {
  447. var col_name = $(this).find("input:checkbox").eq(0).val();
  448. var hidden_input = $("<input/>")
  449. .prop({
  450. name: "move_columns[]",
  451. type: "hidden"
  452. })
  453. .val(col_name);
  454. columns[columns.length] = $("<li/>")
  455. .addClass("placeholderDrag")
  456. .text(col_name)
  457. .append(hidden_input);
  458. });
  459. var col_list = $("#move_columns_dialog ul")
  460. .find("li").remove().end();
  461. for (var i in columns) {
  462. col_list.append(columns[i]);
  463. }
  464. col_list.sortable({
  465. axis: 'y',
  466. containment: $("#move_columns_dialog div"),
  467. tolerance: 'pointer'
  468. }).disableSelection();
  469. var $form = $("#move_columns_dialog form");
  470. $form.data("serialized-unmoved", $form.serialize());
  471. $("#move_columns_dialog").dialog({
  472. modal: true,
  473. buttons: button_options,
  474. beforeClose: function () {
  475. $("#move_columns_anchor").removeClass("move-active");
  476. }
  477. });
  478. });
  479. });
  480. /** Handler for "More" dropdown in structure table rows */
  481. AJAX.registerOnload('tbl_structure.js', function () {
  482. if ($('#fieldsForm').hasClass('HideStructureActions')) {
  483. $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback);
  484. }
  485. });
  486. AJAX.registerTeardown('tbl_structure.js', function () {
  487. $('#fieldsForm ul.table-structure-actions').menuResizer('destroy');
  488. });
  489. $(function () {
  490. $(window).resize($.throttle(function () {
  491. var $list = $('#fieldsForm ul.table-structure-actions');
  492. if ($list.length) {
  493. $list.menuResizer('resize');
  494. }
  495. }));
  496. });