1 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 * @fileoverview functions used wherever an sql query form is used
6 * @requires js/functions.js
11 * decode a string URL_encoded
14 * @return string the URL-decoded string
17 function PMA_urldecode(str) {
18 return decodeURIComponent(str.replace(/\+/g, '%20'));
21 function PMA_urlencode(str) {
22 return encodeURIComponent(str.replace(/\%20/g, '+'));
26 * Get the field name for the current field. Required to construct the query
29 * @param $this_field jQuery object that points to the current field's tr
30 * @param disp_mode string
32 function getFieldName($this_field, disp_mode) {
34 if(disp_mode == 'vertical') {
35 var field_name = $this_field.siblings('th').find('a').text();
36 // happens when just one row (headings contain no a)
37 if ("" == field_name) {
38 field_name = $this_field.siblings('th').text();
42 var this_field_index = $this_field.index();
43 // ltr or rtl direction does not impact how the DOM was generated
45 // 5 columns to account for the checkbox, edit, appended inline edit, copy and delete anchors but index is zero-based so substract 4
46 var field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index-4 )+') a').text();
47 // happens when just one row (headings contain no a)
48 if ("" == field_name) {
49 field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index-4 )+')').text();
53 field_name = $.trim(field_name);
59 * The function that iterates over each row in the table_results and appends a
60 * new inline edit anchor to each table row.
63 function appendInlineAnchor() {
64 var disp_mode = $("#top_direction_dropdown").val();
66 if (disp_mode == 'vertical') {
67 // there can be one or two tr containing this class, depending
68 // on the ModifyDeleteAtLeft and ModifyDeleteAtRight cfg parameters
69 $('#table_results tr')
70 .find('.edit_row_anchor')
71 .removeClass('edit_row_anchor')
72 .parent().each(function() {
73 var $this_tr = $(this);
74 var $cloned_tr = $this_tr.clone();
76 var $img_object = $cloned_tr.find('img:first').attr('title', PMA_messages['strInlineEdit']);
77 if ($img_object.length != 0) {
78 var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit');
79 $img_object.attr('src', img_src);
83 .addClass('inline_edit_anchor')
84 .find('a').attr('href', '#')
86 .text(' ' + PMA_messages['strInlineEdit'])
87 .prepend($img_object);
89 $cloned_tr.insertAfter($this_tr);
92 $('#rowsDeleteForm').find('tbody').find('th').each(function() {
93 var $this_th = $(this);
94 if ($this_th.attr('rowspan') == 4) {
95 $this_th.attr('rowspan', '5');
101 $('.edit_row_anchor').each(function() {
103 var $this_td = $(this);
104 $this_td.removeClass('edit_row_anchor');
106 var $cloned_anchor = $this_td.clone();
108 var $img_object = $cloned_anchor.find('img').attr('title', PMA_messages['strInlineEdit']);
109 if ($img_object.length != 0) {
110 var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit');
111 $img_object.attr('src', img_src);
113 .find('a').attr('href', '#')
115 .text(' ' + PMA_messages['strInlineEdit']);
119 .prepend($img_object);
121 // the link was too big so <input type="image"> is there
122 $img_object = $cloned_anchor.find('input:image').attr('title', PMA_messages['strInlineEdit']);
123 var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit');
124 $img_object.attr('src', img_src);
126 .find('.clickprevimage')
127 .text(' ' + PMA_messages['strInlineEdit']);
131 .addClass('inline_edit_anchor');
133 $this_td.after($cloned_anchor);
136 $('#rowsDeleteForm').find('thead, tbody').find('th').each(function() {
137 var $this_th = $(this);
138 if ($this_th.attr('colspan') == 4) {
139 $this_th.attr('colspan', '5');
150 * @description <p>Ajax scripts for sql and browse pages</p>
152 * Actions ajaxified here:
154 * <li>Retrieve results of an SQL query</li>
155 * <li>Paginate the results table</li>
156 * <li>Sort the results table</li>
157 * <li>Change table according to display options</li>
158 * <li>Inline editing of data</li>
161 * @name document.ready
164 $(document).ready(function() {
167 * Set a parameter for all Ajax queries made on this page. Don't let the
168 * web server serve cached pages
175 * current value of the direction in which the table is displayed
180 var disp_mode = $("#top_direction_dropdown").val();
183 * Update value of {@link jQuery.disp_mode} everytime the direction dropdown changes value
185 * @name direction_dropdown_change
187 $("#top_direction_dropdown, #bottom_direction_dropdown").live('change', function(event) {
188 disp_mode = $(this).val();
192 * Attach the {@link appendInlineAnchor} function to a custom event, which
193 * will be triggered manually everytime the table of results is reloaded
196 $("#sqlqueryresults").live('appendAnchor',function() {
197 appendInlineAnchor();
201 * Trigger the appendAnchor event to prepare the first table for inline edit
202 * (see $GLOBALS['cfg']['AjaxEnable'])
204 * @name sqlqueryresults_trigger
206 $("#sqlqueryresults.ajax").trigger('appendAnchor');
209 * Append the "Show/Hide query box" message to the query input form
212 * @name appendToggleSpan
214 // do not add this link more than once
215 if (! $('#sqlqueryform').find('a').is('#togglequerybox')) {
216 $('<a id="togglequerybox"></a>')
217 .html(PMA_messages['strHideQueryBox'])
218 .appendTo("#sqlqueryform")
219 // initially hidden because at this point, nothing else
220 // appears under the link
223 // Attach the toggling of the query box visibility to a click
224 $("#togglequerybox").bind('click', function() {
226 $link.siblings().slideToggle("fast");
227 if ($link.text() == PMA_messages['strHideQueryBox']) {
228 $link.text(PMA_messages['strShowQueryBox']);
229 // cheap trick to add a spacer between the menu tabs
230 // and "Show query box"; feel free to improve!
231 $('#togglequerybox_spacer').remove();
232 $link.before('<br id="togglequerybox_spacer" />');
234 $link.text(PMA_messages['strHideQueryBox']);
236 // avoid default click action
242 * Ajax Event handler for 'SQL Query Submit'
244 * @see PMA_ajaxShowMessage()
245 * @see $cfg['AjaxEnable']
247 * @name sqlqueryform_submit
249 $("#sqlqueryform.ajax").live('submit', function(event) {
250 event.preventDefault();
251 // remove any div containing a previous error message
252 $('.error').remove();
255 var $msgbox = PMA_ajaxShowMessage();
257 PMA_prepareForAjaxRequest($form);
259 $.post($(this).attr('action'), $(this).serialize() , function(data) {
260 if(data.success == true) {
261 // fade out previous messages, if any
262 $('.success').fadeOut();
263 $('.sqlquery_message').fadeOut();
264 // show a message that stays on screen
265 if (typeof data.sql_query != 'undefined') {
266 $('<div class="sqlquery_message"></div>')
267 .html(data.sql_query)
268 .insertBefore('#sqlqueryform');
269 // unnecessary div that came from data.sql_query
270 $('.notice').remove();
272 $('#sqlqueryform').before(data.message);
274 $('#sqlqueryresults').show();
275 // this happens if a USE command was typed
276 if (typeof data.reload != 'undefined') {
277 // Unbind the submit event before reloading. See bug #3295529
278 $("#sqlqueryform.ajax").die('submit');
279 $form.find('input[name=db]').val(data.db);
280 // need to regenerate the whole upper part
281 $form.find('input[name=ajax_request]').remove();
282 $form.append('<input type="hidden" name="reload" value="true" />');
283 $.post('db_sql.php', $form.serialize(), function(data) {
284 $('body').html(data);
285 }); // end inner post
288 else if (data.success == false ) {
289 // show an error message that stays on screen
290 $('#sqlqueryform').before(data.error);
291 $('#sqlqueryresults').hide();
294 // real results are returned
295 // fade out previous messages, if any
296 $('.success').fadeOut();
297 $('.sqlquery_message').fadeOut();
298 $received_data = $(data);
299 $zero_row_results = $received_data.find('textarea[name="sql_query"]');
300 // if zero rows are returned from the query execution
301 if ($zero_row_results.length > 0) {
302 $('#sqlquery').val($zero_row_results.val());
304 $('#sqlqueryresults').show();
305 $("#sqlqueryresults").html(data);
306 $("#sqlqueryresults").trigger('appendAnchor');
307 $('#togglequerybox').show();
308 if($("#togglequerybox").siblings(":visible").length > 0) {
309 $("#togglequerybox").trigger('click');
314 PMA_ajaxRemoveMessage($msgbox);
317 }) // end SQL Query submit
320 * Ajax Event handlers for Paginating the results table
324 * Paginate when we click any of the navigation buttons
325 * (only if the element has the ajax class, see $cfg['AjaxEnable'])
327 * @name paginate_nav_button_click
328 * @uses PMA_ajaxShowMessage()
329 * @see $cfg['AjaxEnable']
331 $("input[name=navig].ajax").live('click', function(event) {
333 event.preventDefault();
335 var $msgbox = PMA_ajaxShowMessage();
338 * @var $the_form Object referring to the form element that paginates the results table
340 var $the_form = $(this).parent("form");
342 $the_form.append('<input type="hidden" name="ajax_request" value="true" />');
344 $.post($the_form.attr('action'), $the_form.serialize(), function(data) {
345 $("#sqlqueryresults").html(data);
346 $("#sqlqueryresults").trigger('appendAnchor');
349 PMA_ajaxRemoveMessage($msgbox);
351 })// end Paginate results table
354 * Paginate results with Page Selector dropdown
356 * @name paginate_dropdown_change
357 * @see $cfg['AjaxEnable']
359 $("#pageselector").live('change', function(event) {
360 var $the_form = $(this).parent("form");
362 if ($(this).hasClass('ajax')) {
363 event.preventDefault();
365 var $msgbox = PMA_ajaxShowMessage();
367 $.post($the_form.attr('action'), $the_form.serialize() + '&ajax_request=true', function(data) {
368 $("#sqlqueryresults").html(data);
369 $("#sqlqueryresults").trigger('appendAnchor');
371 PMA_ajaxRemoveMessage($msgbox);
377 })// end Paginate results with Page Selector
380 * Ajax Event handler for sorting the results table
382 * @name table_results_sort_click
383 * @see $cfg['AjaxEnable']
385 $("#table_results.ajax").find("a[title=Sort]").live('click', function(event) {
386 event.preventDefault();
388 var $msgbox = PMA_ajaxShowMessage();
392 $.get($anchor.attr('href'), $anchor.serialize() + '&ajax_request=true', function(data) {
393 $("#sqlqueryresults")
395 .trigger('appendAnchor');
396 PMA_ajaxRemoveMessage($msgbox);
398 })//end Sort results table
401 * Ajax Event handler for the display options
403 * @name displayOptionsForm_submit
404 * @see $cfg['AjaxEnable']
406 $("#displayOptionsForm.ajax").live('submit', function(event) {
407 event.preventDefault();
411 $.post($form.attr('action'), $form.serialize() + '&ajax_request=true' , function(data) {
412 $("#sqlqueryresults")
414 .trigger('appendAnchor');
418 //end displayOptionsForm handler
421 * Ajax Event handlers for Inline Editing
425 * On click, replace the fields of current row with an input/textarea
427 * @name inline_edit_start
428 * @see PMA_ajaxShowMessage()
429 * @see getFieldName()
431 $(".inline_edit_anchor span a").live('click', function(event) {
433 event.preventDefault();
435 var $edit_td = $(this).parents('td');
436 $edit_td.removeClass('inline_edit_anchor').addClass('inline_edit_active').parent('tr').addClass('noclick');
438 // Adding submit and hide buttons to inline edit <td>.
439 // For "hide" button the original data to be restored is
440 // kept in the jQuery data element 'original_data' inside the <td>.
441 // Looping through all columns or rows, to find the required data and then storing it in an array.
443 var $this_children = $edit_td.children('span.nowrap').children('a').children('span.nowrap');
444 if (disp_mode != 'vertical') {
445 $this_children.empty();
446 $this_children.text(PMA_messages['strSave']);
449 data_vt = $this_children.html();
450 $this_children.text(PMA_messages['strSave']);
453 var hide_link = '<br /><br /><a id="hide">' + PMA_messages['strHide'] + '</a>';
454 if (disp_mode != 'vertical') {
455 $edit_td.append(hide_link);
456 $('#table_results tbody tr td a#hide').click(function() {
457 $this_children = $(this).siblings('span.nowrap').children('a').children('span.nowrap');
458 $this_children.empty();
459 $this_children.text(PMA_messages['strInlineEdit']);
461 var $this_hide = $(this).parent();
462 $this_hide.removeClass("inline_edit_active hover").addClass("inline_edit_anchor");
463 $this_hide.parent().removeClass("hover noclick");
464 $this_hide.siblings().removeClass("hover");
466 var last_column = $this_hide.siblings().length;
468 for(var i = 4; i < last_column; i++) {
469 if($this_hide.siblings("td:eq(" + i + ")").hasClass("inline_edit") == false) {
472 txt = $this_hide.siblings("td:eq(" + i + ")").data('original_data');
473 if($this_hide.siblings("td:eq(" + i + ")").children().length != 0) {
474 $this_hide.siblings("td:eq(" + i + ")").empty();
475 $this_hide.siblings("td:eq(" + i + ")").append(txt);
478 $(this).prev().prev().remove();
479 $(this).prev().remove();
484 var rows = $edit_td.parent().siblings().length;
486 $edit_td.append(hide_link);
487 $('#table_results tbody tr td a#hide').click(function() {
488 var pos = $(this).parent().index();
489 var $chg_submit = $(this).parent().children('span.nowrap').children('a').children('span.nowrap');
491 $chg_submit.append(data_vt);
493 var $this_row = $(this).parents('tr');
494 // changing inline_edit_active to inline_edit_anchor
495 $this_row.siblings("tr:eq(3) td:eq(" + pos + ")").removeClass("inline_edit_active").addClass("inline_edit_anchor");
497 // removing marked and hover classes.
498 $this_row.parent('tbody').find('tr').find("td:eq(" + pos + ")").removeClass("marked hover");
500 for( var i = 6; i <= rows + 2; i++){
501 if( $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").hasClass("inline_edit") == false) {
504 txt = $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").data('original_data');
505 $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").empty();
506 $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").append(txt);
508 $(this).prev().remove();
509 $(this).prev().remove();
514 // Initialize some variables
515 if(disp_mode == 'vertical') {
517 * @var this_row_index Index of the current <td> in the parent <tr>
518 * Current <td> is the inline edit anchor.
520 var this_row_index = $edit_td.index();
522 * @var $input_siblings Object referring to all inline editable events from same row
524 var $input_siblings = $edit_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_row_index+')');
526 * @var where_clause String containing the WHERE clause to select this row
528 var where_clause = $edit_td.parents('tbody').find('tr').find('.where_clause:nth('+this_row_index+')').val();
532 var this_row_index = $edit_td.parent().index();
533 var $input_siblings = $edit_td.parent('tr').find('.inline_edit');
534 var where_clause = $edit_td.parent('tr').find('.where_clause').val();
537 $input_siblings.each(function() {
540 * @var data_value Current value of this field
542 var data_value = $(this).html();
544 // We need to retrieve the value from the server for truncated/relation fields
545 // Find the field name
548 * @var this_field Object referring to this field (<td>)
550 var $this_field = $(this);
552 * @var field_name String containing the name of this field.
553 * @see getFieldName()
555 var field_name = getFieldName($this_field, disp_mode);
557 * @var relation_curr_value String current value of the field (for fields that are foreign keyed).
559 var relation_curr_value = $this_field.find('a').text();
561 * @var relation_key_or_display_column String relational key if in 'Relational display column' mode,
562 * relational display column if in 'Relational key' mode (for fields that are foreign keyed).
564 var relation_key_or_display_column = $this_field.find('a').attr('title');
566 * @var curr_value String current value of the field (for fields that are of type enum or set).
568 var curr_value = $this_field.text();
570 if($this_field.is(':not(.not_null)')){
571 // add a checkbox to mark null for all the field that are nullable.
572 $this_field.html('<div class="null_div">Null :<input type="checkbox" class="checkbox_null_'+ field_name + '_' + this_row_index +'"></div>');
573 // check the 'checkbox_null_<field_name>_<row_index>' if the corresponding value is null
574 if($this_field.is('.null')) {
575 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', true);
578 // if the select/editor is changed un-check the 'checkbox_null_<field_name>_<row_index>'.
579 if ($this_field.is('.enum, .set')) {
580 $this_field.find('select').live('change', function(e) {
581 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
583 } else if ($this_field.is('.relation')) {
584 $this_field.find('select').live('change', function(e) {
585 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
587 $this_field.find('.browse_foreign').live('click', function(e) {
588 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
591 $this_field.find('textarea').live('keypress', function(e) {
592 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
596 // if 'checkbox_null_<field_name>_<row_index>' is clicked empty the corresponding select/editor.
597 $('.checkbox_null_' + field_name + '_' + this_row_index).bind('click', function(e) {
598 if ($this_field.is('.enum')) {
599 $this_field.find('select').attr('value', '');
600 } else if ($this_field.is('.set')) {
601 $this_field.find('select').find('option').each(function() {
602 var $option = $(this);
603 $option.attr('selected', false);
605 } else if ($this_field.is('.relation')) {
606 // if the dropdown is there to select the foreign value
607 if ($this_field.find('select').length > 0) {
608 $this_field.find('select').attr('value', '');
609 // if foriegn value is selected by browsing foreing values
611 $this_field.find('span.curr_value').empty();
614 $this_field.find('textarea').val('');
619 $this_field.html('<div class="null_div"></div>');
622 // In each input sibling, wrap the current value in a textarea
623 // and store the current value in a hidden span
624 if($this_field.is(':not(.truncated, .transformed, .relation, .enum, .set, .null)')) {
625 // handle non-truncated, non-transformed, non-relation values
626 // We don't need to get any more data, just wrap the value
627 $this_field.append('<textarea>'+data_value+'</textarea>');
628 $this_field.data('original_data', data_value);
630 else if($this_field.is('.truncated, .transformed')) {
632 //handle truncated/transformed values values
635 * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data
637 var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause);
639 // Make the Ajax call and get the data, wrap it and insert it
641 'token' : window.parent.token,
642 'db' : window.parent.db,
643 'ajax_request' : true,
644 'sql_query' : sql_query,
647 if(data.success == true) {
648 $this_field.append('<textarea>'+data.value+'</textarea>');
649 $this_field.data('original_data', data_value);
652 PMA_ajaxShowMessage(data.error);
656 else if($this_field.is('.relation')) {
661 * @var post_params Object containing parameters for the POST request
664 'ajax_request' : true,
665 'get_relational_values' : true,
666 'db' : window.parent.db,
667 'table' : window.parent.table,
668 'column' : field_name,
669 'token' : window.parent.token,
670 'curr_value' : relation_curr_value,
671 'relation_key_or_display_column' : relation_key_or_display_column
674 $.post('sql.php', post_params, function(data) {
675 $this_field.append(data.dropdown);
676 $this_field.data('original_data', data_value);
679 else if($this_field.is('.enum')) {
684 * @var post_params Object containing parameters for the POST request
687 'ajax_request' : true,
688 'get_enum_values' : true,
689 'db' : window.parent.db,
690 'table' : window.parent.table,
691 'column' : field_name,
692 'token' : window.parent.token,
693 'curr_value' : curr_value
695 $.post('sql.php', post_params, function(data) {
696 $this_field.append(data.dropdown);
697 $this_field.data('original_data', data_value);
700 else if($this_field.is('.set')) {
705 * @var post_params Object containing parameters for the POST request
708 'ajax_request' : true,
709 'get_set_values' : true,
710 'db' : window.parent.db,
711 'table' : window.parent.table,
712 'column' : field_name,
713 'token' : window.parent.token,
714 'curr_value' : curr_value
717 $.post('sql.php', post_params, function(data) {
718 $this_field.append(data.select);
719 $this_field.data('original_data', data_value);
722 else if($this_field.is('.null')) {
724 $this_field.append('<textarea></textarea>');
725 $this_field.data('original_data', 'NULL');
728 }) // End On click, replace the current field with an input/textarea
731 * After editing, clicking again should post data
734 * @name inline_edit_save
735 * @see PMA_ajaxShowMessage()
736 * @see getFieldName()
738 $(".inline_edit_active span a").live('click', function(event) {
741 event.preventDefault();
744 * @var $this_td Object referring to the td containing the
745 * "Inline Edit" link that was clicked to save the row that is
749 var $this_td = $(this).parent().parent();
750 var $test_element = ''; // to test the presence of a element
752 // Initialize variables
753 if(disp_mode == 'vertical') {
755 * @var this_td_index Index of the current <td> in the parent <tr>
756 * Current <td> is the inline edit anchor.
758 var this_td_index = $this_td.index();
760 * @var $input_siblings Object referring to all inline editable events from same row
762 var $input_siblings = $this_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_td_index+')');
764 * @var where_clause String containing the WHERE clause to select this row
766 var where_clause = $this_td.parents('tbody').find('tr').find('.where_clause:nth('+this_td_index+')').val();
768 var $input_siblings = $this_td.parent('tr').find('.inline_edit');
769 var where_clause = $this_td.parent('tr').find('.where_clause').val();
773 * @var nonunique Boolean, whether this row is unique or not
775 if($this_td.is('.nonunique')) {
782 // Collect values of all fields to submit, we don't know which changed
784 * @var relation_fields Array containing the name/value pairs of relational fields
786 var relation_fields = {};
788 * @var relational_display string 'K' if relational key, 'D' if relational display column
790 var relational_display = $("#relational_display_K").attr('checked') ? 'K' : 'D';
792 * @var transform_fields Array containing the name/value pairs for transformed fields
794 var transform_fields = {};
796 * @var transformation_fields Boolean, if there are any transformed fields in this row
798 var transformation_fields = false;
801 * @var sql_query String containing the SQL query to update this row
803 var sql_query = 'UPDATE `' + window.parent.table + '` SET ';
805 var need_to_post = false;
810 $input_siblings.each(function() {
813 * @var this_field Object referring to this field (<td>)
815 var $this_field = $(this);
818 * @var field_name String containing the name of this field.
819 * @see getFieldName()
821 var field_name = getFieldName($this_field, disp_mode);
824 * @var this_field_params Array temporary storage for the name/value of current field
826 var this_field_params = {};
828 if($this_field.is('.transformed')) {
829 transformation_fields = true;
832 * @var is_null String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked.
834 var is_null = $this_field.find('input:checkbox').is(':checked');
838 sql_query += ' `' + field_name + "`=NULL , ";
841 if($this_field.is(":not(.relation, .enum, .set)")) {
842 this_field_params[field_name] = $this_field.find('textarea').val();
843 if($this_field.is('.transformed')) {
844 $.extend(transform_fields, this_field_params);
846 } else if ($this_field.is('.set')) {
847 $test_element = $this_field.find('select');
848 this_field_params[field_name] = $test_element.map(function(){
849 return $(this).val();
852 // results from a drop-down
853 $test_element = $this_field.find('select');
854 if ($test_element.length != 0) {
855 this_field_params[field_name] = $test_element.val();
858 // results from Browse foreign value
859 $test_element = $this_field.find('span.curr_value');
860 if ($test_element.length != 0) {
861 this_field_params[field_name] = $test_element.text();
864 if($this_field.is('.relation')) {
865 $.extend(relation_fields, this_field_params);
868 if(where_clause.indexOf(field_name) > prev_index){
869 new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND ';
871 if (this_field_params[field_name] != $this_field.data('original_data')) {
872 sql_query += ' `' + field_name + "`='" + this_field_params[field_name].replace(/'/g, "''") + "' , ";
879 * update the where_clause, remove the last appended ' AND '
882 //Remove the last ',' appended in the above loop
883 sql_query = sql_query.replace(/,\s$/, '');
884 new_clause = new_clause.substring(0, new_clause.length-5);
885 new_clause = PMA_urlencode(new_clause);
886 sql_query += ' WHERE ' + PMA_urldecode(where_clause);
888 * @var rel_fields_list String, url encoded representation of {@link relations_fields}
890 var rel_fields_list = $.param(relation_fields);
893 * @var transform_fields_list String, url encoded representation of {@link transform_fields}
895 var transform_fields_list = $.param(transform_fields);
897 // if inline_edit is successful, we need to go back to default view
898 var $del_hide = $(this).parent();
899 var $chg_submit = $(this);
902 // Make the Ajax post after setting all parameters
904 * @var post_params Object containing parameters for the POST request
906 var post_params = {'ajax_request' : true,
907 'sql_query' : sql_query,
908 'disp_direction' : disp_mode,
909 'token' : window.parent.token,
910 'db' : window.parent.db,
911 'table' : window.parent.table,
912 'clause_is_unique' : nonunique,
913 'where_clause' : where_clause,
914 'rel_fields_list' : rel_fields_list,
915 'do_transformations' : transformation_fields,
916 'transform_fields_list' : transform_fields_list,
917 'relational_display' : relational_display,
919 'submit_type' : 'save'
922 $.post('tbl_replace.php', post_params, function(data) {
923 if(data.success == true) {
924 PMA_ajaxShowMessage(data.message);
925 if(disp_mode == 'vertical') {
926 $this_td.parents('tbody').find('tr').find('.where_clause:nth(' + this_td_index + ')').attr('value', new_clause);
929 $this_td.parent('tr').find('.where_clause').attr('value', new_clause);
931 // remove possible previous feedback message
932 $('#result_query').remove();
933 if (typeof data.sql_query != 'undefined') {
935 $('#sqlqueryresults').prepend(data.sql_query);
937 PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode);
939 PMA_ajaxShowMessage(data.error);
943 // no posting was done but still need to display the row
944 // in its previous format
945 PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, '', disp_mode);
947 }) // End After editing, clicking again should post data
948 }, 'top.frame_content') // end $(document).ready()
952 * Visually put back the row in the state it was before entering Inline edit
954 * (when called in the situation where no posting was done, the data
955 * parameter is empty)
957 function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode) {
959 // deleting the hide button
960 // remove <br><br><a> tags
961 for ( var i = 0; i <= 2; i++) {
962 $del_hide.next().remove();
964 if(disp_mode != 'vertical'){
966 $chg_submit.html('<span class="nowrap"></span>');
967 $chg_submit.children('span.nowrap').text(PMA_messages['strInlineEdit']);
969 $chg_submit.children('span.nowrap').empty();
970 $chg_submit.children('span.nowrap').append(data_vt);
973 // changing inline_edit_active to inline_edit_anchor
974 $this_td.removeClass('inline_edit_active').addClass('inline_edit_anchor');
976 // removing hover, marked and noclick classes
977 $this_td.parent('tr').removeClass('noclick');
978 if(disp_mode != 'vertical') {
979 $this_td.parent('tr').removeClass('hover').find('td').removeClass('hover');
981 $this_td.parents('tbody').find('tr').find('td:eq(' + $this_td.index() + ')').removeClass('marked');
984 $input_siblings.each(function() {
985 // Inline edit post has been successful.
986 $this_sibling = $(this);
988 var is_null = $this_sibling.find('input:checkbox').is(':checked');
990 $this_sibling.html('NULL');
991 $this_sibling.addClass('null');
993 $this_sibling.removeClass('null');
994 if($this_sibling.is(':not(.relation, .enum, .set)')) {
996 * @var new_html String containing value of the data field after edit
998 var new_html = $this_sibling.find('textarea').val();
1000 if($this_sibling.is('.transformed')) {
1001 var field_name = getFieldName($this_sibling, disp_mode);
1002 if (typeof data.transformations != 'undefined') {
1003 $.each(data.transformations, function(key, value) {
1004 if(key == field_name) {
1005 if($this_sibling.is('.text_plain, .application_octetstream')) {
1009 var new_value = $this_sibling.find('textarea').val();
1010 new_html = $(value).append(new_value);
1020 $test_element = $this_sibling.find('select');
1021 if ($test_element.length != 0) {
1022 new_value = $test_element.val();
1024 $test_element = $this_sibling.find('span.curr_value');
1025 if ($test_element.length != 0) {
1026 new_value = $test_element.text();
1029 if($this_sibling.is('.relation')) {
1030 var field_name = getFieldName($this_sibling, disp_mode);
1031 if (typeof data.relations != 'undefined') {
1032 $.each(data.relations, function(key, value) {
1033 if(key == field_name) {
1034 new_html = $(value);
1039 } else if ($this_sibling.is('.enum')) {
1040 new_html = new_value;
1041 } else if ($this_sibling.is('.set')) {
1042 if (new_value != null) {
1043 $.each(new_value, function(key, value) {
1044 new_html = new_html + value + ',';
1046 new_html = new_html.substring(0, new_html.length-1);
1050 $this_sibling.html(new_html);
1056 * Starting from some th, change the class of all td under it
1058 function PMA_changeClassForColumn($this_th, newclass) {
1059 // index 0 is the th containing the big T
1060 var th_index = $this_th.index();
1061 var has_big_t = !$this_th.closest('tr').children(':first').hasClass('column_heading');
1062 // .eq() is zero-based
1066 var $tds = $this_th.closest('table').find('tbody tr').find('td.data:eq('+th_index+')');
1067 if ($this_th.data('has_class_'+newclass)) {
1068 $tds.removeClass(newclass);
1069 $this_th.data('has_class_'+newclass, false);
1071 $tds.addClass(newclass);
1072 $this_th.data('has_class_'+newclass, true);
1076 $(document).ready(function() {
1078 $('.browse_foreign').live('click', function(e) {
1080 window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes,resizable=yes');
1082 $anchor.addClass('browse_foreign_clicked');
1087 * vertical column highlighting in horizontal mode when hovering over the column header
1089 $('.column_heading').live('hover', function() {
1090 PMA_changeClassForColumn($(this), 'hover');
1094 * vertical column marking in horizontal mode when clicking the column header
1096 $('.column_heading').live('click', function() {
1097 PMA_changeClassForColumn($(this), 'marked');