Bug #3188108 Inline edit break the hyperlink of foreign keyed value
[phpmyadmin-themes.git] / js / sql.js
blob0132a8c79d9becef5e2a3e9ac2f13da8e5ece2bc
1 /* vim: set expandtab sw=4 ts=4 sts=4: */
2 /**
3  * @fileoverview    functions used wherever an sql query form is used
4  *
5  * @requires    jQuery
6  * @requires    js/functions.js
7  *
8  */
10 /**
11  * decode a string URL_encoded
12  *
13  * @param string str
14  * @return string the URL-decoded string
15  */
16 function PMA_urldecode(str) {
17     return decodeURIComponent(str.replace(/\+/g, '%20'));
20 /**
21  * Get the field name for the current field.  Required to construct the query
22  * for inline editing
23  *
24  * @param   $this_field  jQuery object that points to the current field's tr
25  * @param   disp_mode    string
26  */
27 function getFieldName($this_field, disp_mode) {
29     if(disp_mode == 'vertical') {
30         var field_name = $this_field.siblings('th').find('a').text();
31         // happens when just one row (headings contain no a)
32         if ("" == field_name) {
33             field_name = $this_field.siblings('th').text();
34         }
35     }
36     else {
37         var this_field_index = $this_field.index();
38         // ltr or rtl direction does not impact how the DOM was generated
39         //
40         // 5 columns to account for the checkbox, edit, appended inline edit, copy and delete anchors but index is zero-based so substract 4
41         var field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index-4 )+') a').text();
42         // happens when just one row (headings contain no a)
43         if ("" == field_name) {
44             field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index-4 )+')').text();
45         }
46     }
48     field_name = $.trim(field_name);
50     return field_name;
53 /**
54  * The function that iterates over each row in the table_results and appends a
55  * new inline edit anchor to each table row.
56  *
57  */
58 function appendInlineAnchor() {
59     var disp_mode = $("#top_direction_dropdown").val();
61     if (disp_mode == 'vertical') {
62         // there can be one or two tr containing this class, depending
63         // on the ModifyDeleteAtLeft and ModifyDeleteAtRight cfg parameters
64         $('#table_results tr')
65             .find('.edit_row_anchor')
66             .removeClass('.edit_row_anchor')
67             .parent().each(function() {
68             var $this_tr = $(this);
69             var $cloned_tr = $this_tr.clone();
71             var $img_object = $cloned_tr.find('img:first').attr('title', PMA_messages['strInlineEdit']);
72             var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit');
73             $img_object.attr('src', img_src);
75             $cloned_tr.find('td')
76              .addClass('inline_edit_anchor')
77              .find('a').attr('href', '#')
78              .find('span')
79              .text(' ' + PMA_messages['strInlineEdit'])
80              .prepend($img_object);
82             $cloned_tr.insertAfter($this_tr);
83         });
85         $('#rowsDeleteForm').find('tbody').find('th').each(function() {
86             var $this_th = $(this);
87             if ($this_th.attr('rowspan') == 4) {
88                 $this_th.attr('rowspan', '5');
89             }
90         });
91     }
92     else {
93         $('.edit_row_anchor').each(function() {
95             $this_td = $(this)
96             $this_td.removeClass('edit_row_anchor');
98             var $cloned_anchor = $this_td.clone();
100             var $img_object = $cloned_anchor.find('img').attr('title', PMA_messages['strInlineEdit']);
101             var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit');
102             $img_object.attr('src', img_src);
104             $cloned_anchor.addClass('inline_edit_anchor')
105             .find('a').attr('href', '#')
106             .find('span')
107             .text(' ' + PMA_messages['strInlineEdit'])
108             .prepend($img_object);
110             $this_td.after($cloned_anchor);
111         });
113         $('#rowsDeleteForm').find('thead, tbody').find('th').each(function() {
114             var $this_th = $(this);
115             if ($this_th.attr('colspan') == 4) {
116                 $this_th.attr('colspan', '5');
117             }
118         });
119     }
122 /**#@+
123  * @namespace   jQuery
124  */
127  * @description <p>Ajax scripts for sql and browse pages</p>
129  * Actions ajaxified here:
130  * <ul>
131  * <li>Retrieve results of an SQL query</li>
132  * <li>Paginate the results table</li>
133  * <li>Sort the results table</li>
134  * <li>Change table according to display options</li>
135  * <li>Inline editing of data</li>
136  * </ul>
138  * @name        document.ready
139  * @memberOf    jQuery
140  */
141 $(document).ready(function() {
143     /**
144      * Set a parameter for all Ajax queries made on this page.  Don't let the
145      * web server serve cached pages
146      */
147     $.ajaxSetup({
148         cache: 'false'
149     });
151     /**
152      * current value of the direction in which the table is displayed
153      * @type    String
154      * @fieldOf jQuery
155      * @name    disp_mode
156      */
157     var disp_mode = $("#top_direction_dropdown").val();
159     /**
160      * Update value of {@link jQuery.disp_mode} everytime the direction dropdown changes value
161      * @memberOf    jQuery
162      * @name        direction_dropdown_change
163      */
164     $("#top_direction_dropdown, #bottom_direction_dropdown").live('change', function(event) {
165         disp_mode = $(this).val();
166     })
168     /**
169      * Attach the {@link appendInlineAnchor} function to a custom event, which
170      * will be triggered manually everytime the table of results is reloaded
171      * @memberOf    jQuery
172      */
173     $("#sqlqueryresults").live('appendAnchor',function() {
174         appendInlineAnchor();
175     })
177     /**
178      * Trigger the appendAnchor event to prepare the first table for inline edit
179      * (see $GLOBALS['cfg']['AjaxEnable'])
180      * @memberOf    jQuery
181      * @name        sqlqueryresults_trigger
182      */
183     $("#sqlqueryresults.ajax").trigger('appendAnchor');
185     /**
186      * Append the "Show/Hide query box" message to the query input form
187      *
188      * @memberOf jQuery
189      * @name    appendToggleSpan
190      */
191     // do not add this link more than once
192     if (! $('#sqlqueryform').find('a').is('#togglequerybox')) {
193         $('<a id="togglequerybox"></a>')
194         .html(PMA_messages['strHideQueryBox'])
195         .appendTo("#sqlqueryform")
196         // initially hidden because at this point, nothing else
197         // appears under the link
198         .hide();
200         // Attach the toggling of the query box visibility to a click
201         $("#togglequerybox").bind('click', function() {
202             var $link = $(this)
203             $link.siblings().slideToggle("fast");
204             if ($link.text() == PMA_messages['strHideQueryBox']) {
205                 $link.text(PMA_messages['strShowQueryBox']);
206                 // cheap trick to add a spacer between the menu tabs
207                 // and "Show query box"; feel free to improve!
208                 $('#togglequerybox_spacer').remove();
209                 $link.before('<br id="togglequerybox_spacer" />');
210             } else {
211                 $link.text(PMA_messages['strHideQueryBox']);
212             }
213             // avoid default click action
214             return false;
215         })
216     }
218     /**
219      * Ajax Event handler for 'SQL Query Submit'
220      *
221      * @see         PMA_ajaxShowMessage()
222      * @see         $cfg['AjaxEnable']
223      * @memberOf    jQuery
224      * @name        sqlqueryform_submit
225      */
226     $("#sqlqueryform.ajax").live('submit', function(event) {
227         event.preventDefault();
228         // remove any div containing a previous error message
229         $('.error').remove();
231         $form = $(this);
232         PMA_ajaxShowMessage();
234         if (! $form.find('input:hidden').is('#ajax_request_hidden')) {
235             $form.append('<input type="hidden" id="ajax_request_hidden" name="ajax_request" value="true" />');
236         }
238         $.post($(this).attr('action'), $(this).serialize() , function(data) {
239             if(data.success == true) {
240                 // fade out previous messages, if any
241                 $('.success').fadeOut();
242                 $('.sqlquery_message').fadeOut();
243                 // show a message that stays on screen
244                 $('#sqlqueryform').before(data.message);
245                 // and display the query
246                 $('<div class="sqlquery_message"></div>')
247                  .html(data.sql_query)
248                  .insertBefore('#sqlqueryform');
249                 // unnecessary div that came from data.sql_query
250                 $('.notice').remove();
251                 $('#sqlqueryresults').show();
252                 // this happens if a USE command was typed
253                 if (typeof data.reload != 'undefined') {
254                     $form.find('input[name=db]').val(data.db);
255                     // need to regenerate the whole upper part
256                     $form.find('input[name=ajax_request]').remove();
257                     $form.append('<input type="hidden" name="reload" value="true" />');
258                     $.post('db_sql.php', $form.serialize(), function(data) {
259                         $('body').html(data);
260                     }); // end inner post
261                 }
262             }
263             else if (data.success == false ) {
264                 // show an error message that stays on screen
265                 $('#sqlqueryform').before(data.error);
266                 $('#sqlqueryresults').hide();
267             }
268             else {
269                 // real results are returned
270                 $('#sqlqueryresults').show();
271                 $("#sqlqueryresults").html(data);
272                 $("#sqlqueryresults").trigger('appendAnchor');
273                 $('#togglequerybox').show();
274                 if($("#togglequerybox").siblings(":visible").length > 0) {
275                     $("#togglequerybox").trigger('click');
276                 }
277                 PMA_init_slider();
278             }
279         }) // end $.post()
280     }) // end SQL Query submit
282     /**
283      * Ajax Event handlers for Paginating the results table
284      */
286     /**
287      * Paginate when we click any of the navigation buttons
288      * (only if the element has the ajax class, see $cfg['AjaxEnable'])
289      * @memberOf    jQuery
290      * @name        paginate_nav_button_click
291      * @uses        PMA_ajaxShowMessage()
292      * @see         $cfg['AjaxEnable']
293      */
294     $("input[name=navig].ajax").live('click', function(event) {
295         /** @lends jQuery */
296         event.preventDefault();
298         PMA_ajaxShowMessage();
300         /**
301          * @var $the_form    Object referring to the form element that paginates the results table
302          */
303         var $the_form = $(this).parent("form");
305         $the_form.append('<input type="hidden" name="ajax_request" value="true" />');
307         $.post($the_form.attr('action'), $the_form.serialize(), function(data) {
308             $("#sqlqueryresults").html(data);
309             $("#sqlqueryresults").trigger('appendAnchor');
310             PMA_init_slider();
311         }) // end $.post()
312     })// end Paginate results table
314     /**
315      * Paginate results with Page Selector dropdown
316      * @memberOf    jQuery
317      * @name        paginate_dropdown_change
318      * @see         $cfg['AjaxEnable']
319      */
320     $("#pageselector").live('change', function(event) {
321         var $the_form = $(this).parent("form");
323         if ($(this).hasClass('ajax')) {
324             event.preventDefault();
326             PMA_ajaxShowMessage();
328             $.post($the_form.attr('action'), $the_form.serialize() + '&ajax_request=true', function(data) {
329                 $("#sqlqueryresults").html(data);
330                 $("#sqlqueryresults").trigger('appendAnchor');
331                 PMA_init_slider();
332             }) // end $.post()
333         } else {
334             $the_form.submit();
335         }
337     })// end Paginate results with Page Selector
339     /**
340      * Ajax Event handler for sorting the results table
341      * @memberOf    jQuery
342      * @name        table_results_sort_click
343      * @see         $cfg['AjaxEnable']
344      */
345     $("#table_results.ajax").find("a[title=Sort]").live('click', function(event) {
346         event.preventDefault();
348         PMA_ajaxShowMessage();
350         $anchor = $(this);
352         $.get($anchor.attr('href'), $anchor.serialize() + '&ajax_request=true', function(data) {
353             $("#sqlqueryresults")
354              .html(data)
355              .trigger('appendAnchor');
356         }) // end $.get()
357     })//end Sort results table
359     /**
360      * Ajax Event handler for the display options
361      * @memberOf    jQuery
362      * @name        displayOptionsForm_submit
363      * @see         $cfg['AjaxEnable']
364      */
365     $("#displayOptionsForm.ajax").live('submit', function(event) {
366         event.preventDefault();
368         $form = $(this);
370         $.post($form.attr('action'), $form.serialize() + '&ajax_request=true' , function(data) {
371             $("#sqlqueryresults")
372              .html(data)
373              .trigger('appendAnchor');
374             PMA_init_slider();
375         }) // end $.post()
376     })
377     //end displayOptionsForm handler
379     /**
380      * Ajax Event handlers for Inline Editing
381      */
383     /**
384      * On click, replace the fields of current row with an input/textarea
385      * @memberOf    jQuery
386      * @name        inline_edit_start
387      * @see         PMA_ajaxShowMessage()
388      * @see         getFieldName()
389      */
390     $(".inline_edit_anchor").live('click', function(event) {
391         /** @lends jQuery */
392         event.preventDefault();
394         $(this).removeClass('inline_edit_anchor').addClass('inline_edit_active');
396         // Initialize some variables
397         if(disp_mode == 'vertical') {
398             /**
399              * @var this_row_index  Index of the current <td> in the parent <tr>
400              *                      Current <td> is the inline edit anchor.
401              */
402             var this_row_index = $(this).index();
403             /**
404              * @var $input_siblings  Object referring to all inline editable events from same row
405              */
406             var $input_siblings = $(this).parents('tbody').find('tr').find('.inline_edit:nth('+this_row_index+')');
407             /**
408              * @var where_clause    String containing the WHERE clause to select this row
409              */
410             var where_clause = $(this).parents('tbody').find('tr').find('.where_clause:nth('+this_row_index+')').val();
411         }
412         else {
413             var this_row_index = $(this).parent().index();
414             var $input_siblings = $(this).parent('tr').find('.inline_edit');
415             var where_clause = $(this).parent('tr').find('.where_clause').val();
416         }
418         $input_siblings.each(function() {
419             /** @lends jQuery */
420             /**
421              * @var data_value  Current value of this field
422              */
423             var data_value = $(this).html();
425             // We need to retrieve the value from the server for truncated/relation fields
426             // Find the field name
428             /**
429              * @var this_field  Object referring to this field (<td>)
430              */
431             var $this_field = $(this);
432             /**
433              * @var field_name  String containing the name of this field.
434              * @see getFieldName()
435              */
436             var field_name = getFieldName($this_field, disp_mode);
437             /**
438              * @var relation_curr_value String current value of the field (for fields that are foreign keyed).
439              */
440             var relation_curr_value = $this_field.find('a').text();
441             /**
442              * @var enum_curr_value String current value of the field (for fields that are of type enum).
443              */
444             var enum_curr_value = $this_field.text();
446             if($this_field.is(':not(.not_null)')){
447                 // add a checkbox to mark null for all the field that are nullable.
448                 $this_field.html('<div class="null_div">Null :<input type="checkbox" class="checkbox_null_'+ field_name + '_' + this_row_index +'"></div>');
449                 // check the 'checkbox_null_<field_name>_<row_index>' if the corresponding value is null
450                 if($this_field.is('.null')) {
451                     $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', true);
452                 }
454                 // if the select/editor is changed un-check the 'checkbox_null_<field_name>_<row_index>'.
455                 if ($this_field.is('.enum, .set')) {
456                     $this_field.find('select').live('change', function(e) {
457                         $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
458                     })
459                 } else if ($this_field.is('.relation')) {
460                     $this_field.find('select').live('change', function(e) {
461                         $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
462                     })
463                     $this_field.find('.browse_foreign').live('click', function(e) {
464                         $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
465                     })
466                 } else {
467                     $this_field.find('textarea').live('keypress', function(e) {
468                         $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
469                     })
470                 }
472                 // if 'chechbox_null_<field_name>_<row_index>' is clicked empty the corresponding select/editor.
473                 $('.checkbox_null_' + field_name + '_' + this_row_index).bind('click', function(e) {
474                     if ($this_field.is('.enum, .set')) {
475                         $this_field.find('select').selectedIndex = -1;
476                     } else if ($this_field.is('.relation')) {
477                         // if the dropdown is there to select the foreign value
478                         if ($this_field.find('select').length > 0) {
479                             $this_field.find('select').attr('value', '');
480                         // if foriegn value is selected by browsing foreing values
481                         } else {
482                             $this_field.find('span.curr_value').empty();
483                         }
484                     } else {
485                         $this_field.find('textarea').val('');
486                     }
487                 })
489             } else {
490                 $this_field.html('<div class="null_div"></div>');
491             }
493             // In each input sibling, wrap the current value in a textarea
494             // and store the current value in a hidden span
495             if($this_field.is(':not(.truncated, .transformed, .relation, .enum, .null)')) {
496                 // handle non-truncated, non-transformed, non-relation values
497                 // We don't need to get any more data, just wrap the value
498                 $this_field.append('<textarea>'+data_value+'</textarea>');
499                 $this_field.append('<span class="original_data">'+data_value+'</span>');
500                 $(".original_data").hide();
501             }
502             else if($this_field.is('.truncated, .transformed')) {
503                 /** @lends jQuery */
504                 //handle truncated/transformed values values
506                 /**
507                  * @var sql_query   String containing the SQL query used to retrieve value of truncated/transformed data
508                  */
509                 var sql_query = 'SELECT ' + field_name + ' FROM ' + window.parent.table + ' WHERE ' + where_clause;
511                 // Make the Ajax call and get the data, wrap it and insert it
512                 $.post('sql.php', {
513                     'token' : window.parent.token,
514                     'db' : window.parent.db,
515                     'ajax_request' : true,
516                     'sql_query' : sql_query,
517                     'inline_edit' : true
518                 }, function(data) {
519                     if(data.success == true) {
520                         $this_field.append('<textarea>'+data.value+'</textarea>');
521                         $this_field.append('<span class="original_data">'+data_value+'</span>');
522                         $(".original_data").hide();
523                     }
524                     else {
525                         PMA_ajaxShowMessage(data.error);
526                     }
527                 }) // end $.post()
528             }
529             else if($this_field.is('.relation')) {
530                 /** @lends jQuery */
531                 //handle relations
533                 /**
534                  * @var post_params Object containing parameters for the POST request
535                  */
536                 var post_params = {
537                         'ajax_request' : true,
538                         'get_relational_values' : true,
539                         'db' : window.parent.db,
540                         'table' : window.parent.table,
541                         'column' : field_name,
542                         'token' : window.parent.token,
543                         'curr_value' : relation_curr_value
544                 }
546                 $.post('sql.php', post_params, function(data) {
547                     $this_field.append(data.dropdown);
548                     $this_field.append('<span class="original_data">'+data_value+'</span>');
549                     $(".original_data").hide();
550                 }) // end $.post()
551             }
552             else if($this_field.is('.enum')) {
553                 /** @lends jQuery */
554                 //handle enum fields
556                 /**
557                  * @var post_params Object containing parameters for the POST request
558                  */
559                 var post_params = {
560                         'ajax_request' : true,
561                         'get_enum_values' : true,
562                         'db' : window.parent.db,
563                         'table' : window.parent.table,
564                         'column' : field_name,
565                         'token' : window.parent.token,
566                         'curr_value' : enum_curr_value
567                 }
569                 $.post('sql.php', post_params, function(data) {
570                     $this_field.append(data.dropdown);
571                     $this_field.append('<span class="original_data">'+data_value+'</span>');
572                     $(".original_data").hide();
573                 }) // end $.post()
574             }
575             else if($this_field.is('.null')) {
576                 //handle null fields
577                 $this_field.append('<textarea></textarea>');
578                 $this_field.append('<span class="original_data">NULL</span>');
579                 $(".original_data").hide();
580             }
581         })
582     }) // End On click, replace the current field with an input/textarea
584     /**
585      * After editing, clicking again should post data
586      *
587      * @memberOf    jQuery
588      * @name        inline_edit_save
589      * @see         PMA_ajaxShowMessage()
590      * @see         getFieldName()
591      */
592     $(".inline_edit_active").live('click', function(event) {
593         /** @lends jQuery */
594         event.preventDefault();
596         /**
597          * @var $this_td    Object referring to the td containing the
598          * "Inline Edit" link that was clicked to save the row that is
599          * being edited
600          *
601          */
602         var $this_td = $(this);
604         var $test_element = ''; // to test the presence of a element
606         // Initialize variables
607         if(disp_mode == 'vertical') {
608             /**
609              * @var this_td_index  Index of the current <td> in the parent <tr>
610              *                      Current <td> is the inline edit anchor.
611              */
612             var this_td_index = $this_td.index();
613             /**
614              * @var $input_siblings  Object referring to all inline editable events from same row
615              */
616             var $input_siblings = $this_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_td_index+')');
617             /**
618              * @var where_clause    String containing the WHERE clause to select this row
619              */
620             var where_clause = $this_td.parents('tbody').find('tr').find('.where_clause:nth('+this_td_index+')').val();
621         }
622         else {
623             var $input_siblings = $this_td.parent('tr').find('.inline_edit');
624             var where_clause = $this_td.parent('tr').find('.where_clause').val();
625         }
627         /**
628          * @var nonunique   Boolean, whether this row is unique or not
629          */
630         if($this_td.is('.nonunique')) {
631             var nonunique = 0;
632         }
633         else {
634             var nonunique = 1;
635         }
637         // Collect values of all fields to submit, we don't know which changed
638         /**
639          * @var relation_fields Array containing the name/value pairs of relational fields
640          */
641         var relation_fields = {};
642         /**
643          * @var transform_fields    Array containing the name/value pairs for transformed fields
644          */
645         var transform_fields = {};
646         /**
647          * @var transformation_fields   Boolean, if there are any transformed fields in this row
648          */
649         var transformation_fields = false;
651         /**
652          * @var sql_query String containing the SQL query to update this row
653          */
654         var sql_query = 'UPDATE ' + window.parent.table + ' SET ';
656         $input_siblings.each(function() {
657             /** @lends jQuery */
658             /**
659              * @var this_field  Object referring to this field (<td>)
660              */
661             var $this_field = $(this);
662             /**
663              * @var field_name  String containing the name of this field.
664              * @see getFieldName()
665              */
666             var field_name = getFieldName($this_field, disp_mode);
668             /**
669              * @var this_field_params   Array temporary storage for the name/value of current field
670              */
671             var this_field_params = {};
673             if($this_field.is('.transformed')) {
674                 transformation_fields =  true;
675             }
676             /**
677              * @var is_null String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked.
678              */
679             var is_null = $this_field.find('input:checkbox').is(':checked');
680             var value;
682             if (is_null) {
683                 sql_query += ' ' + field_name + "=NULL , ";
684             } else {
685                 if($this_field.is(":not(.relation, .enum)")) {
686                     this_field_params[field_name] = $this_field.find('textarea').val();
687                     if($this_field.is('.transformed')) {
688                         $.extend(transform_fields, this_field_params);
689                     }
690                 }
691                 else {
692                     // results from a drop-down
693                     $test_element = $this_field.find('select');
694                     if ($test_element.length != 0) {
695                         this_field_params[field_name] = $test_element.val();
696                     }
698                     // results from Browse foreign value
699                     $test_element = $this_field.find('span.curr_value');
700                     if ($test_element.length != 0) {
701                         this_field_params[field_name] = $test_element.text();
702                     }
704                     if($this_field.is('.relation')) {
705                         $.extend(relation_fields, this_field_params);
706                     }
707                 }
709                 sql_query += ' ' + field_name + "='" + this_field_params[field_name].replace(/'/g, "''") + "' , ";
710             }
711         })
713         //Remove the last ',' appended in the above loop
714         sql_query = sql_query.replace(/,\s$/, '');
715         sql_query += ' WHERE ' + PMA_urldecode(where_clause);
717         /**
718          * @var rel_fields_list  String, url encoded representation of {@link relations_fields}
719          */
720         var rel_fields_list = $.param(relation_fields);
722         /**
723          * @var transform_fields_list  String, url encoded representation of {@link transform_fields}
724          */
725         var transform_fields_list = $.param(transform_fields);
727         // Make the Ajax post after setting all parameters
728         /**
729          * @var post_params Object containing parameters for the POST request
730          */
731         var post_params = {'ajax_request' : true,
732                             'sql_query' : sql_query,
733                             'disp_direction' : disp_mode,
734                             'token' : window.parent.token,
735                             'db' : window.parent.db,
736                             'table' : window.parent.table,
737                             'clause_is_unique' : nonunique,
738                             'where_clause' : where_clause,
739                             'rel_fields_list' : rel_fields_list,
740                             'do_transformations' : transformation_fields,
741                             'transform_fields_list' : transform_fields_list,
742                             'goto' : 'sql.php',
743                             'submit_type' : 'save'
744                           };
746         $.post('tbl_replace.php', post_params, function(data) {
747             if(data.success == true) {
748                 PMA_ajaxShowMessage(data.message);
749                 $this_td.removeClass('inline_edit_active').addClass('inline_edit_anchor');
751                 $input_siblings.each(function() {
752                     // Inline edit post has been successful.
753                     $this_sibling = $(this);
755                     var is_null = $this_sibling.find('input:checkbox').is(':checked');
756                     if (is_null) {
757                         $this_sibling.html('NULL');
758                         $this_sibling.addClass('null');
759                     } else {
760                         $this_sibling.removeClass('null');
761                         if($this_sibling.is(':not(.relation, .enum)')) {
762                             /**
763                              * @var new_html    String containing value of the data field after edit
764                              */
765                             var new_html = $this_sibling.find('textarea').val();
767                             if($this_sibling.is('.transformed')) {
768                                 var field_name = getFieldName($this_sibling, disp_mode);
769                                 $.each(data.transformations, function(key, value) {
770                                     if(key == field_name) {
771                                         if($this_sibling.is('.text_plain, .application_octetstream')) {
772                                             new_html = value;
773                                             return false;
774                                         }
775                                         else {
776                                             var new_value = $this_sibling.find('textarea').val();
777                                             new_html = $(value).append(new_value);
778                                             return false;
779                                         }
780                                     }
781                                 })
782                             }
783                         }
784                         else {
785                             var new_html = '';
786                             var new_value = '';
787                             $test_element = $this_sibling.find('select');
788                             if ($test_element.length != 0) {
789                                 new_value = $test_element.val();
790                             }
792                             $test_element = $this_sibling.find('span.curr_value');
793                             if ($test_element.length != 0) {
794                                 new_value = $test_element.text();
795                             }
797                             if($this_sibling.is('.relation')) {
798                                 var field_name = getFieldName($this_sibling, disp_mode);
799                                 $.each(data.relations, function(key, value) {
800                                     if(key == field_name) {
801                                         new_html = $(value).append(new_value);
802                                         return false;
803                                     }
804                                 })
805                             }
806                             if($this_sibling.is('.enum')) {
807                                 new_html = new_value;
808                             }
809                         }
810                         $this_sibling.html(new_html);
811                     }
812                 })
813             }
814             else {
815                 PMA_ajaxShowMessage(data.error);
816             };
817         }) // end $.post()
818     }) // End After editing, clicking again should post data
819 }, 'top.frame_content') // end $(document).ready()
822  * Starting from some th, change the class of all td under it
823  */
824 function PMA_changeClassForColumn($this_th, newclass) {
825     // index 0 is the th containing the big T
826     var th_index = $this_th.index();
827     // .eq() is zero-based
828     th_index--;
829     var $tr_with_data = $this_th.closest('table').find('tbody tr ').has('td.data');
830     $tr_with_data.each(function() {
831         $(this).find('td.data:eq('+th_index+')').toggleClass(newclass);
832     });
835 $(document).ready(function() {
837     $('.browse_foreign').live('click', function(e) {
838         e.preventDefault();
839         window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes,resizable=yes');
840         $anchor = $(this);
841         $anchor.addClass('browse_foreign_clicked');
842         return false;
843     });
845     /**
846      * vertical column highlighting in horizontal mode when hovering over the column header
847      */
848     $('.column_heading').live('hover', function() {
849         PMA_changeClassForColumn($(this), 'hover');
850         });
852     /**
853      * vertical column marking in horizontal mode when clicking the column header
854      */
855     $('.column_heading').live('click', function() {
856         PMA_changeClassForColumn($(this), 'marked');
857         });
860 /**#@- */