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 $form.find('input[name=db]').val(data.db);
278 // need to regenerate the whole upper part
279 $form.find('input[name=ajax_request]').remove();
280 $form.append('<input type="hidden" name="reload" value="true" />');
281 $.post('db_sql.php', $form.serialize(), function(data) {
282 $('body').html(data);
283 }); // end inner post
286 else if (data.success == false ) {
287 // show an error message that stays on screen
288 $('#sqlqueryform').before(data.error);
289 $('#sqlqueryresults').hide();
292 // real results are returned
293 // fade out previous messages, if any
294 $('.success').fadeOut();
295 $('.sqlquery_message').fadeOut();
296 $received_data = $(data);
297 $zero_row_results = $received_data.find('textarea[name="sql_query"]');
298 // if zero rows are returned from the query execution
299 if ($zero_row_results.length > 0) {
300 $('#sqlquery').val($zero_row_results.val());
302 $('#sqlqueryresults').show();
303 $("#sqlqueryresults").html(data);
304 $("#sqlqueryresults").trigger('appendAnchor');
305 $('#togglequerybox').show();
306 if($("#togglequerybox").siblings(":visible").length > 0) {
307 $("#togglequerybox").trigger('click');
312 PMA_ajaxRemoveMessage($msgbox);
315 }) // end SQL Query submit
318 * Ajax Event handlers for Paginating the results table
322 * Paginate when we click any of the navigation buttons
323 * (only if the element has the ajax class, see $cfg['AjaxEnable'])
325 * @name paginate_nav_button_click
326 * @uses PMA_ajaxShowMessage()
327 * @see $cfg['AjaxEnable']
329 $("input[name=navig].ajax").live('click', function(event) {
331 event.preventDefault();
333 var $msgbox = PMA_ajaxShowMessage();
336 * @var $the_form Object referring to the form element that paginates the results table
338 var $the_form = $(this).parent("form");
340 $the_form.append('<input type="hidden" name="ajax_request" value="true" />');
342 $.post($the_form.attr('action'), $the_form.serialize(), function(data) {
343 $("#sqlqueryresults").html(data);
344 $("#sqlqueryresults").trigger('appendAnchor');
347 PMA_ajaxRemoveMessage($msgbox);
349 })// end Paginate results table
352 * Paginate results with Page Selector dropdown
354 * @name paginate_dropdown_change
355 * @see $cfg['AjaxEnable']
357 $("#pageselector").live('change', function(event) {
358 var $the_form = $(this).parent("form");
360 if ($(this).hasClass('ajax')) {
361 event.preventDefault();
363 var $msgbox = PMA_ajaxShowMessage();
365 $.post($the_form.attr('action'), $the_form.serialize() + '&ajax_request=true', function(data) {
366 $("#sqlqueryresults").html(data);
367 $("#sqlqueryresults").trigger('appendAnchor');
369 PMA_ajaxRemoveMessage($msgbox);
375 })// end Paginate results with Page Selector
378 * Ajax Event handler for sorting the results table
380 * @name table_results_sort_click
381 * @see $cfg['AjaxEnable']
383 $("#table_results.ajax").find("a[title=Sort]").live('click', function(event) {
384 event.preventDefault();
386 var $msgbox = PMA_ajaxShowMessage();
390 $.get($anchor.attr('href'), $anchor.serialize() + '&ajax_request=true', function(data) {
391 $("#sqlqueryresults")
393 .trigger('appendAnchor');
394 PMA_ajaxRemoveMessage($msgbox);
396 })//end Sort results table
399 * Ajax Event handler for the display options
401 * @name displayOptionsForm_submit
402 * @see $cfg['AjaxEnable']
404 $("#displayOptionsForm.ajax").live('submit', function(event) {
405 event.preventDefault();
409 $.post($form.attr('action'), $form.serialize() + '&ajax_request=true' , function(data) {
410 $("#sqlqueryresults")
412 .trigger('appendAnchor');
416 //end displayOptionsForm handler
419 * Ajax Event handlers for Inline Editing
423 * On click, replace the fields of current row with an input/textarea
425 * @name inline_edit_start
426 * @see PMA_ajaxShowMessage()
427 * @see getFieldName()
429 $(".inline_edit_anchor span a").live('click', function(event) {
431 event.preventDefault();
433 var $edit_td = $(this).parents('td');
434 $edit_td.removeClass('inline_edit_anchor').addClass('inline_edit_active').parent('tr').addClass('noclick');
436 // Adding submit and hide buttons to inline edit <td>.
437 // For "hide" button the original data to be restored is
438 // kept in the jQuery data element 'original_data' inside the <td>.
439 // Looping through all columns or rows, to find the required data and then storing it in an array.
441 var $this_children = $edit_td.children('span.nowrap').children('a').children('span.nowrap');
442 if (disp_mode != 'vertical') {
443 $this_children.empty();
444 $this_children.text(PMA_messages['strSave']);
447 data_vt = $this_children.html();
448 $this_children.text(PMA_messages['strSave']);
451 var hide_link = '<br /><br /><a id="hide">' + PMA_messages['strHide'] + '</a>';
452 if (disp_mode != 'vertical') {
453 $edit_td.append(hide_link);
454 $('#table_results tbody tr td a#hide').click(function() {
455 $this_children = $(this).siblings('span.nowrap').children('a').children('span.nowrap');
456 $this_children.empty();
457 $this_children.text(PMA_messages['strInlineEdit']);
459 var $this_hide = $(this).parent();
460 $this_hide.removeClass("inline_edit_active hover").addClass("inline_edit_anchor");
461 $this_hide.parent().removeClass("hover noclick");
462 $this_hide.siblings().removeClass("hover");
464 var last_column = $this_hide.siblings().length;
466 for(var i = 4; i < last_column; i++) {
467 if($this_hide.siblings("td:eq(" + i + ")").hasClass("inline_edit") == false) {
470 txt = $this_hide.siblings("td:eq(" + i + ")").data('original_data');
471 if($this_hide.siblings("td:eq(" + i + ")").children().length != 0) {
472 $this_hide.siblings("td:eq(" + i + ")").empty();
473 $this_hide.siblings("td:eq(" + i + ")").append(txt);
476 $(this).prev().prev().remove();
477 $(this).prev().remove();
482 var rows = $edit_td.parent().siblings().length;
484 $edit_td.append(hide_link);
485 $('#table_results tbody tr td a#hide').click(function() {
486 var pos = $(this).parent().index();
487 var $chg_submit = $(this).parent().children('span.nowrap').children('a').children('span.nowrap');
489 $chg_submit.append(data_vt);
491 var $this_row = $(this).parents('tr');
492 // changing inline_edit_active to inline_edit_anchor
493 $this_row.siblings("tr:eq(3) td:eq(" + pos + ")").removeClass("inline_edit_active").addClass("inline_edit_anchor");
495 // removing marked and hover classes.
496 $this_row.parent('tbody').find('tr').find("td:eq(" + pos + ")").removeClass("marked hover");
498 for( var i = 6; i <= rows + 2; i++){
499 if( $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").hasClass("inline_edit") == false) {
502 txt = $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").data('original_data');
503 $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").empty();
504 $this_row.siblings("tr:eq(" + i + ") td:eq(" + pos + ")").append(txt);
506 $(this).prev().remove();
507 $(this).prev().remove();
512 // Initialize some variables
513 if(disp_mode == 'vertical') {
515 * @var this_row_index Index of the current <td> in the parent <tr>
516 * Current <td> is the inline edit anchor.
518 var this_row_index = $edit_td.index();
520 * @var $input_siblings Object referring to all inline editable events from same row
522 var $input_siblings = $edit_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_row_index+')');
524 * @var where_clause String containing the WHERE clause to select this row
526 var where_clause = $edit_td.parents('tbody').find('tr').find('.where_clause:nth('+this_row_index+')').val();
530 var this_row_index = $edit_td.parent().index();
531 var $input_siblings = $edit_td.parent('tr').find('.inline_edit');
532 var where_clause = $edit_td.parent('tr').find('.where_clause').val();
535 $input_siblings.each(function() {
538 * @var data_value Current value of this field
540 var data_value = $(this).html();
542 // We need to retrieve the value from the server for truncated/relation fields
543 // Find the field name
546 * @var this_field Object referring to this field (<td>)
548 var $this_field = $(this);
550 * @var field_name String containing the name of this field.
551 * @see getFieldName()
553 var field_name = getFieldName($this_field, disp_mode);
555 * @var relation_curr_value String current value of the field (for fields that are foreign keyed).
557 var relation_curr_value = $this_field.find('a').text();
559 * @var relation_key_or_display_column String relational key if in 'Relational display column' mode,
560 * relational display column if in 'Relational key' mode (for fields that are foreign keyed).
562 var relation_key_or_display_column = $this_field.find('a').attr('title');
564 * @var curr_value String current value of the field (for fields that are of type enum or set).
566 var curr_value = $this_field.text();
568 if($this_field.is(':not(.not_null)')){
569 // add a checkbox to mark null for all the field that are nullable.
570 $this_field.html('<div class="null_div">Null :<input type="checkbox" class="checkbox_null_'+ field_name + '_' + this_row_index +'"></div>');
571 // check the 'checkbox_null_<field_name>_<row_index>' if the corresponding value is null
572 if($this_field.is('.null')) {
573 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', true);
576 // if the select/editor is changed un-check the 'checkbox_null_<field_name>_<row_index>'.
577 if ($this_field.is('.enum, .set')) {
578 $this_field.find('select').live('change', function(e) {
579 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
581 } else if ($this_field.is('.relation')) {
582 $this_field.find('select').live('change', function(e) {
583 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
585 $this_field.find('.browse_foreign').live('click', function(e) {
586 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
589 $this_field.find('textarea').live('keypress', function(e) {
590 $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
594 // if 'checkbox_null_<field_name>_<row_index>' is clicked empty the corresponding select/editor.
595 $('.checkbox_null_' + field_name + '_' + this_row_index).bind('click', function(e) {
596 if ($this_field.is('.enum')) {
597 $this_field.find('select').attr('value', '');
598 } else if ($this_field.is('.set')) {
599 $this_field.find('select').find('option').each(function() {
600 var $option = $(this);
601 $option.attr('selected', false);
603 } else if ($this_field.is('.relation')) {
604 // if the dropdown is there to select the foreign value
605 if ($this_field.find('select').length > 0) {
606 $this_field.find('select').attr('value', '');
607 // if foriegn value is selected by browsing foreing values
609 $this_field.find('span.curr_value').empty();
612 $this_field.find('textarea').val('');
617 $this_field.html('<div class="null_div"></div>');
620 // In each input sibling, wrap the current value in a textarea
621 // and store the current value in a hidden span
622 if($this_field.is(':not(.truncated, .transformed, .relation, .enum, .set, .null)')) {
623 // handle non-truncated, non-transformed, non-relation values
624 // We don't need to get any more data, just wrap the value
625 $this_field.append('<textarea>'+data_value+'</textarea>');
626 $this_field.data('original_data', data_value);
628 else if($this_field.is('.truncated, .transformed')) {
630 //handle truncated/transformed values values
633 * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data
635 var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause);
637 // Make the Ajax call and get the data, wrap it and insert it
639 'token' : window.parent.token,
640 'db' : window.parent.db,
641 'ajax_request' : true,
642 'sql_query' : sql_query,
645 if(data.success == true) {
646 $this_field.append('<textarea>'+data.value+'</textarea>');
647 $this_field.data('original_data', data_value);
650 PMA_ajaxShowMessage(data.error);
654 else if($this_field.is('.relation')) {
659 * @var post_params Object containing parameters for the POST request
662 'ajax_request' : true,
663 'get_relational_values' : true,
664 'db' : window.parent.db,
665 'table' : window.parent.table,
666 'column' : field_name,
667 'token' : window.parent.token,
668 'curr_value' : relation_curr_value,
669 'relation_key_or_display_column' : relation_key_or_display_column
672 $.post('sql.php', post_params, function(data) {
673 $this_field.append(data.dropdown);
674 $this_field.data('original_data', data_value);
677 else if($this_field.is('.enum')) {
682 * @var post_params Object containing parameters for the POST request
685 'ajax_request' : true,
686 'get_enum_values' : true,
687 'db' : window.parent.db,
688 'table' : window.parent.table,
689 'column' : field_name,
690 'token' : window.parent.token,
691 'curr_value' : curr_value
693 $.post('sql.php', post_params, function(data) {
694 $this_field.append(data.dropdown);
695 $this_field.data('original_data', data_value);
698 else if($this_field.is('.set')) {
703 * @var post_params Object containing parameters for the POST request
706 'ajax_request' : true,
707 'get_set_values' : true,
708 'db' : window.parent.db,
709 'table' : window.parent.table,
710 'column' : field_name,
711 'token' : window.parent.token,
712 'curr_value' : curr_value
715 $.post('sql.php', post_params, function(data) {
716 $this_field.append(data.select);
717 $this_field.data('original_data', data_value);
720 else if($this_field.is('.null')) {
722 $this_field.append('<textarea></textarea>');
723 $this_field.data('original_data', 'NULL');
726 }) // End On click, replace the current field with an input/textarea
729 * After editing, clicking again should post data
732 * @name inline_edit_save
733 * @see PMA_ajaxShowMessage()
734 * @see getFieldName()
736 $(".inline_edit_active span a").live('click', function(event) {
739 event.preventDefault();
742 * @var $this_td Object referring to the td containing the
743 * "Inline Edit" link that was clicked to save the row that is
747 var $this_td = $(this).parent().parent();
748 var $test_element = ''; // to test the presence of a element
750 // Initialize variables
751 if(disp_mode == 'vertical') {
753 * @var this_td_index Index of the current <td> in the parent <tr>
754 * Current <td> is the inline edit anchor.
756 var this_td_index = $this_td.index();
758 * @var $input_siblings Object referring to all inline editable events from same row
760 var $input_siblings = $this_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_td_index+')');
762 * @var where_clause String containing the WHERE clause to select this row
764 var where_clause = $this_td.parents('tbody').find('tr').find('.where_clause:nth('+this_td_index+')').val();
766 var $input_siblings = $this_td.parent('tr').find('.inline_edit');
767 var where_clause = $this_td.parent('tr').find('.where_clause').val();
771 * @var nonunique Boolean, whether this row is unique or not
773 if($this_td.is('.nonunique')) {
780 // Collect values of all fields to submit, we don't know which changed
782 * @var relation_fields Array containing the name/value pairs of relational fields
784 var relation_fields = {};
786 * @var relational_display string 'K' if relational key, 'D' if relational display column
788 var relational_display = $("#relational_display_K").attr('checked') ? 'K' : 'D';
790 * @var transform_fields Array containing the name/value pairs for transformed fields
792 var transform_fields = {};
794 * @var transformation_fields Boolean, if there are any transformed fields in this row
796 var transformation_fields = false;
799 * @var sql_query String containing the SQL query to update this row
801 var sql_query = 'UPDATE `' + window.parent.table + '` SET ';
803 var need_to_post = false;
808 $input_siblings.each(function() {
811 * @var this_field Object referring to this field (<td>)
813 var $this_field = $(this);
816 * @var field_name String containing the name of this field.
817 * @see getFieldName()
819 var field_name = getFieldName($this_field, disp_mode);
822 * @var this_field_params Array temporary storage for the name/value of current field
824 var this_field_params = {};
826 if($this_field.is('.transformed')) {
827 transformation_fields = true;
830 * @var is_null String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked.
832 var is_null = $this_field.find('input:checkbox').is(':checked');
836 sql_query += ' `' + field_name + "`=NULL , ";
839 if($this_field.is(":not(.relation, .enum, .set)")) {
840 this_field_params[field_name] = $this_field.find('textarea').val();
841 if($this_field.is('.transformed')) {
842 $.extend(transform_fields, this_field_params);
844 } else if ($this_field.is('.set')) {
845 $test_element = $this_field.find('select');
846 this_field_params[field_name] = $test_element.map(function(){
847 return $(this).val();
850 // results from a drop-down
851 $test_element = $this_field.find('select');
852 if ($test_element.length != 0) {
853 this_field_params[field_name] = $test_element.val();
856 // results from Browse foreign value
857 $test_element = $this_field.find('span.curr_value');
858 if ($test_element.length != 0) {
859 this_field_params[field_name] = $test_element.text();
862 if($this_field.is('.relation')) {
863 $.extend(relation_fields, this_field_params);
866 if(where_clause.indexOf(field_name) > prev_index){
867 new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND ';
869 if (this_field_params[field_name] != $this_field.data('original_data')) {
870 sql_query += ' `' + field_name + "`='" + this_field_params[field_name].replace(/'/g, "''") + "' , ";
877 * update the where_clause, remove the last appended ' AND '
880 //Remove the last ',' appended in the above loop
881 sql_query = sql_query.replace(/,\s$/, '');
882 new_clause = new_clause.substring(0, new_clause.length-5);
883 new_clause = PMA_urlencode(new_clause);
884 sql_query += ' WHERE ' + PMA_urldecode(where_clause);
886 * @var rel_fields_list String, url encoded representation of {@link relations_fields}
888 var rel_fields_list = $.param(relation_fields);
891 * @var transform_fields_list String, url encoded representation of {@link transform_fields}
893 var transform_fields_list = $.param(transform_fields);
895 // if inline_edit is successful, we need to go back to default view
896 var $del_hide = $(this).parent();
897 var $chg_submit = $(this);
900 // Make the Ajax post after setting all parameters
902 * @var post_params Object containing parameters for the POST request
904 var post_params = {'ajax_request' : true,
905 'sql_query' : sql_query,
906 'disp_direction' : disp_mode,
907 'token' : window.parent.token,
908 'db' : window.parent.db,
909 'table' : window.parent.table,
910 'clause_is_unique' : nonunique,
911 'where_clause' : where_clause,
912 'rel_fields_list' : rel_fields_list,
913 'do_transformations' : transformation_fields,
914 'transform_fields_list' : transform_fields_list,
915 'relational_display' : relational_display,
917 'submit_type' : 'save'
920 $.post('tbl_replace.php', post_params, function(data) {
921 if(data.success == true) {
922 PMA_ajaxShowMessage(data.message);
923 if(disp_mode == 'vertical') {
924 $this_td.parents('tbody').find('tr').find('.where_clause:nth(' + this_td_index + ')').attr('value', new_clause);
927 $this_td.parent('tr').find('.where_clause').attr('value', new_clause);
929 // remove possible previous feedback message
930 $('#result_query').remove();
931 if (typeof data.sql_query != 'undefined') {
933 $('#sqlqueryresults').prepend(data.sql_query);
935 PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode);
937 PMA_ajaxShowMessage(data.error);
941 // no posting was done but still need to display the row
942 // in its previous format
943 PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, '', disp_mode);
945 }) // End After editing, clicking again should post data
946 }, 'top.frame_content') // end $(document).ready()
950 * Visually put back the row in the state it was before entering Inline edit
952 * (when called in the situation where no posting was done, the data
953 * parameter is empty)
955 function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode) {
957 // deleting the hide button
958 // remove <br><br><a> tags
959 for ( var i = 0; i <= 2; i++) {
960 $del_hide.next().remove();
962 if(disp_mode != 'vertical'){
964 $chg_submit.html('<span class="nowrap"></span>');
965 $chg_submit.children('span.nowrap').text(PMA_messages['strInlineEdit']);
967 $chg_submit.children('span.nowrap').empty();
968 $chg_submit.children('span.nowrap').append(data_vt);
971 // changing inline_edit_active to inline_edit_anchor
972 $this_td.removeClass('inline_edit_active').addClass('inline_edit_anchor');
974 // removing hover, marked and noclick classes
975 $this_td.parent('tr').removeClass('noclick');
976 if(disp_mode != 'vertical') {
977 $this_td.parent('tr').removeClass('hover').find('td').removeClass('hover');
979 $this_td.parents('tbody').find('tr').find('td:eq(' + $this_td.index() + ')').removeClass('marked');
982 $input_siblings.each(function() {
983 // Inline edit post has been successful.
984 $this_sibling = $(this);
986 var is_null = $this_sibling.find('input:checkbox').is(':checked');
988 $this_sibling.html('NULL');
989 $this_sibling.addClass('null');
991 $this_sibling.removeClass('null');
992 if($this_sibling.is(':not(.relation, .enum, .set)')) {
994 * @var new_html String containing value of the data field after edit
996 var new_html = $this_sibling.find('textarea').val();
998 if($this_sibling.is('.transformed')) {
999 var field_name = getFieldName($this_sibling, disp_mode);
1000 if (typeof data.transformations != 'undefined') {
1001 $.each(data.transformations, function(key, value) {
1002 if(key == field_name) {
1003 if($this_sibling.is('.text_plain, .application_octetstream')) {
1007 var new_value = $this_sibling.find('textarea').val();
1008 new_html = $(value).append(new_value);
1018 $test_element = $this_sibling.find('select');
1019 if ($test_element.length != 0) {
1020 new_value = $test_element.val();
1022 $test_element = $this_sibling.find('span.curr_value');
1023 if ($test_element.length != 0) {
1024 new_value = $test_element.text();
1027 if($this_sibling.is('.relation')) {
1028 var field_name = getFieldName($this_sibling, disp_mode);
1029 if (typeof data.relations != 'undefined') {
1030 $.each(data.relations, function(key, value) {
1031 if(key == field_name) {
1032 new_html = $(value);
1037 } else if ($this_sibling.is('.enum')) {
1038 new_html = new_value;
1039 } else if ($this_sibling.is('.set')) {
1040 if (new_value != null) {
1041 $.each(new_value, function(key, value) {
1042 new_html = new_html + value + ',';
1044 new_html = new_html.substring(0, new_html.length-1);
1048 $this_sibling.html(new_html);
1054 * Starting from some th, change the class of all td under it
1056 function PMA_changeClassForColumn($this_th, newclass) {
1057 // index 0 is the th containing the big T
1058 var th_index = $this_th.index();
1059 var has_big_t = !$this_th.closest('tr').children(':first').hasClass('column_heading');
1060 // .eq() is zero-based
1064 var $tds = $this_th.closest('table').find('tbody tr').find('td.data:eq('+th_index+')');
1065 if ($this_th.data('has_class_'+newclass)) {
1066 $tds.removeClass(newclass);
1067 $this_th.data('has_class_'+newclass, false);
1069 $tds.addClass(newclass);
1070 $this_th.data('has_class_'+newclass, true);
1074 $(document).ready(function() {
1076 $('.browse_foreign').live('click', function(e) {
1078 window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes,resizable=yes');
1080 $anchor.addClass('browse_foreign_clicked');
1085 * vertical column highlighting in horizontal mode when hovering over the column header
1087 $('.column_heading').live('hover', function() {
1088 PMA_changeClassForColumn($(this), 'hover');
1092 * vertical column marking in horizontal mode when clicking the column header
1094 $('.column_heading').live('click', function() {
1095 PMA_changeClassForColumn($(this), 'marked');