Remove author name from variable name
[phpmyadmin/gandalfml.git] / js / sql.js
blob78d7649d2692af229a0397445b4cf4238758d739
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 var data_vt;
17 function PMA_urldecode(str) {
18     return decodeURIComponent(str.replace(/\+/g, '%20'));
21 /**
22  * Get the field name for the current field.  Required to construct the query
23  * for inline editing
24  *
25  * @param   $this_field  jQuery object that points to the current field's tr
26  * @param   disp_mode    string
27  */
28 function getFieldName($this_field, disp_mode) {
30     if(disp_mode == 'vertical') {
31         var field_name = $this_field.siblings('th').find('a').text();
32         // happens when just one row (headings contain no a)
33         if ("" == field_name) {
34             field_name = $this_field.siblings('th').text();
35         }
36     }
37     else {
38         var this_field_index = $this_field.index();
39         // ltr or rtl direction does not impact how the DOM was generated
40         //
41         // 5 columns to account for the checkbox, edit, appended inline edit, copy and delete anchors but index is zero-based so substract 4
42         var field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index-4 )+') a').text();
43         // happens when just one row (headings contain no a)
44         if ("" == field_name) {
45             field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index-4 )+')').text();
46         }
47     }
49     field_name = $.trim(field_name);
51     return field_name;
54 /**
55  * The function that iterates over each row in the table_results and appends a
56  * new inline edit anchor to each table row.
57  *
58  */
59 function appendInlineAnchor() {
60     var disp_mode = $("#top_direction_dropdown").val();
62     if (disp_mode == 'vertical') {
63         // there can be one or two tr containing this class, depending
64         // on the ModifyDeleteAtLeft and ModifyDeleteAtRight cfg parameters
65         $('#table_results tr')
66             .find('.edit_row_anchor')
67             .removeClass('.edit_row_anchor')
68             .parent().each(function() {
69             var $this_tr = $(this);
70             var $cloned_tr = $this_tr.clone();
72             var $img_object = $cloned_tr.find('img:first').attr('title', PMA_messages['strInlineEdit']);
73             if ($img_object.length != 0) {
74                 var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit');
75                 $img_object.attr('src', img_src);
76             }
78             $cloned_tr.find('td')
79              .addClass('inline_edit_anchor')
80              .find('a').attr('href', '#')
81              .find('span')
82              .text(' ' + PMA_messages['strInlineEdit'])
83              .prepend($img_object);
85             $cloned_tr.insertAfter($this_tr);
86         });
88         $('#rowsDeleteForm').find('tbody').find('th').each(function() {
89             var $this_th = $(this);
90             if ($this_th.attr('rowspan') == 4) {
91                 $this_th.attr('rowspan', '5');
92             }
93         });
94     }
95     else {
96         // horizontal mode
97         $('.edit_row_anchor').each(function() {
99             var $this_td = $(this);
100             $this_td.removeClass('edit_row_anchor');
102             var $cloned_anchor = $this_td.clone();
104             var $img_object = $cloned_anchor.find('img').attr('title', PMA_messages['strInlineEdit']);
105             if ($img_object.length != 0) {
106                 var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit');
107                 $img_object.attr('src', img_src);
108                 $cloned_anchor
109                  .find('a').attr('href', '#')
110                  .find('span')
111                  .text(' ' + PMA_messages['strInlineEdit']);
112                 $cloned_anchor
113                  .find('span')
114                  .first()
115                  .prepend($img_object);
116             } else {
117                 // the link was too big so <input type="image"> is there
118                 $img_object = $cloned_anchor.find('input:image').attr('title', PMA_messages['strInlineEdit']);
119                 var img_src = $img_object.attr('src').replace(/b_edit/,'b_inline_edit');
120                 $img_object.attr('src', img_src);
121                 $cloned_anchor
122                  .find('.clickprevimage')
123                  .text(' ' + PMA_messages['strInlineEdit']);
124             }
126             $cloned_anchor
127              .addClass('inline_edit_anchor');
129             $this_td.after($cloned_anchor);
130         });
132         $('#rowsDeleteForm').find('thead, tbody').find('th').each(function() {
133             var $this_th = $(this);
134             if ($this_th.attr('colspan') == 4) {
135                 $this_th.attr('colspan', '5');
136             }
137         });
138     }
141 /**#@+
142  * @namespace   jQuery
143  */
146  * @description <p>Ajax scripts for sql and browse pages</p>
148  * Actions ajaxified here:
149  * <ul>
150  * <li>Retrieve results of an SQL query</li>
151  * <li>Paginate the results table</li>
152  * <li>Sort the results table</li>
153  * <li>Change table according to display options</li>
154  * <li>Inline editing of data</li>
155  * </ul>
157  * @name        document.ready
158  * @memberOf    jQuery
159  */
160 $(document).ready(function() {
162     /**
163      * Set a parameter for all Ajax queries made on this page.  Don't let the
164      * web server serve cached pages
165      */
166     $.ajaxSetup({
167         cache: 'false'
168     });
170     /**
171      * current value of the direction in which the table is displayed
172      * @type    String
173      * @fieldOf jQuery
174      * @name    disp_mode
175      */
176     var disp_mode = $("#top_direction_dropdown").val();
178     /**
179      * Update value of {@link jQuery.disp_mode} everytime the direction dropdown changes value
180      * @memberOf    jQuery
181      * @name        direction_dropdown_change
182      */
183     $("#top_direction_dropdown, #bottom_direction_dropdown").live('change', function(event) {
184         disp_mode = $(this).val();
185     })
187     /**
188      * Attach the {@link appendInlineAnchor} function to a custom event, which
189      * will be triggered manually everytime the table of results is reloaded
190      * @memberOf    jQuery
191      */
192     $("#sqlqueryresults").live('appendAnchor',function() {
193         appendInlineAnchor();
194     })
196     /**
197      * Trigger the appendAnchor event to prepare the first table for inline edit
198      * (see $GLOBALS['cfg']['AjaxEnable'])
199      * @memberOf    jQuery
200      * @name        sqlqueryresults_trigger
201      */
202     $("#sqlqueryresults.ajax").trigger('appendAnchor');
204     /**
205      * Append the "Show/Hide query box" message to the query input form
206      *
207      * @memberOf jQuery
208      * @name    appendToggleSpan
209      */
210     // do not add this link more than once
211     if (! $('#sqlqueryform').find('a').is('#togglequerybox')) {
212         $('<a id="togglequerybox"></a>')
213         .html(PMA_messages['strHideQueryBox'])
214         .appendTo("#sqlqueryform")
215         // initially hidden because at this point, nothing else
216         // appears under the link
217         .hide();
219         // Attach the toggling of the query box visibility to a click
220         $("#togglequerybox").bind('click', function() {
221             var $link = $(this)
222             $link.siblings().slideToggle("fast");
223             if ($link.text() == PMA_messages['strHideQueryBox']) {
224                 $link.text(PMA_messages['strShowQueryBox']);
225                 // cheap trick to add a spacer between the menu tabs
226                 // and "Show query box"; feel free to improve!
227                 $('#togglequerybox_spacer').remove();
228                 $link.before('<br id="togglequerybox_spacer" />');
229             } else {
230                 $link.text(PMA_messages['strHideQueryBox']);
231             }
232             // avoid default click action
233             return false;
234         })
235     }
237     /**
238      * Ajax Event handler for 'SQL Query Submit'
239      *
240      * @see         PMA_ajaxShowMessage()
241      * @see         $cfg['AjaxEnable']
242      * @memberOf    jQuery
243      * @name        sqlqueryform_submit
244      */
245     $("#sqlqueryform.ajax").live('submit', function(event) {
246         event.preventDefault();
247         // remove any div containing a previous error message
248         $('.error').remove();
250         $form = $(this);
251         PMA_ajaxShowMessage();
253         if (! $form.find('input:hidden').is('#ajax_request_hidden')) {
254             $form.append('<input type="hidden" id="ajax_request_hidden" name="ajax_request" value="true" />');
255         }
257         $.post($(this).attr('action'), $(this).serialize() , function(data) {
258             if(data.success == true) {
259                 // fade out previous messages, if any
260                 $('.success').fadeOut();
261                 $('.sqlquery_message').fadeOut();
262                 // show a message that stays on screen
263                 $('#sqlqueryform').before(data.message);
264                 // and display the query
265                 $('<div class="sqlquery_message"></div>')
266                  .html(data.sql_query)
267                  .insertBefore('#sqlqueryform');
268                 // unnecessary div that came from data.sql_query
269                 $('.notice').remove();
270                 $('#sqlqueryresults').show();
271                 // this happens if a USE command was typed
272                 if (typeof data.reload != 'undefined') {
273                     $form.find('input[name=db]').val(data.db);
274                     // need to regenerate the whole upper part
275                     $form.find('input[name=ajax_request]').remove();
276                     $form.append('<input type="hidden" name="reload" value="true" />');
277                     $.post('db_sql.php', $form.serialize(), function(data) {
278                         $('body').html(data);
279                     }); // end inner post
280                 }
281             }
282             else if (data.success == false ) {
283                 // show an error message that stays on screen
284                 $('#sqlqueryform').before(data.error);
285                 $('#sqlqueryresults').hide();
286             }
287             else {
288                 // real results are returned
289                 $('#sqlqueryresults').show();
290                 $("#sqlqueryresults").html(data);
291                 $("#sqlqueryresults").trigger('appendAnchor');
292                 $('#togglequerybox').show();
293                 if($("#togglequerybox").siblings(":visible").length > 0) {
294                     $("#togglequerybox").trigger('click');
295                 }
296                 PMA_init_slider();
297             }
298         }) // end $.post()
299     }) // end SQL Query submit
301     /**
302      * Ajax Event handlers for Paginating the results table
303      */
305     /**
306      * Paginate when we click any of the navigation buttons
307      * (only if the element has the ajax class, see $cfg['AjaxEnable'])
308      * @memberOf    jQuery
309      * @name        paginate_nav_button_click
310      * @uses        PMA_ajaxShowMessage()
311      * @see         $cfg['AjaxEnable']
312      */
313     $("input[name=navig].ajax").live('click', function(event) {
314         /** @lends jQuery */
315         event.preventDefault();
317         PMA_ajaxShowMessage();
319         /**
320          * @var $the_form    Object referring to the form element that paginates the results table
321          */
322         var $the_form = $(this).parent("form");
324         $the_form.append('<input type="hidden" name="ajax_request" value="true" />');
326         $.post($the_form.attr('action'), $the_form.serialize(), function(data) {
327             $("#sqlqueryresults").html(data);
328             $("#sqlqueryresults").trigger('appendAnchor');
329             PMA_init_slider();
330         }) // end $.post()
331     })// end Paginate results table
333     /**
334      * Paginate results with Page Selector dropdown
335      * @memberOf    jQuery
336      * @name        paginate_dropdown_change
337      * @see         $cfg['AjaxEnable']
338      */
339     $("#pageselector").live('change', function(event) {
340         var $the_form = $(this).parent("form");
342         if ($(this).hasClass('ajax')) {
343             event.preventDefault();
345             PMA_ajaxShowMessage();
347             $.post($the_form.attr('action'), $the_form.serialize() + '&ajax_request=true', function(data) {
348                 $("#sqlqueryresults").html(data);
349                 $("#sqlqueryresults").trigger('appendAnchor');
350                 PMA_init_slider();
351             }) // end $.post()
352         } else {
353             $the_form.submit();
354         }
356     })// end Paginate results with Page Selector
358     /**
359      * Ajax Event handler for sorting the results table
360      * @memberOf    jQuery
361      * @name        table_results_sort_click
362      * @see         $cfg['AjaxEnable']
363      */
364     $("#table_results.ajax").find("a[title=Sort]").live('click', function(event) {
365         event.preventDefault();
367         PMA_ajaxShowMessage();
369         $anchor = $(this);
371         $.get($anchor.attr('href'), $anchor.serialize() + '&ajax_request=true', function(data) {
372             $("#sqlqueryresults")
373              .html(data)
374              .trigger('appendAnchor');
375         }) // end $.get()
376     })//end Sort results table
378     /**
379      * Ajax Event handler for the display options
380      * @memberOf    jQuery
381      * @name        displayOptionsForm_submit
382      * @see         $cfg['AjaxEnable']
383      */
384     $("#displayOptionsForm.ajax").live('submit', function(event) {
385         event.preventDefault();
387         $form = $(this);
389         $.post($form.attr('action'), $form.serialize() + '&ajax_request=true' , function(data) {
390             $("#sqlqueryresults")
391              .html(data)
392              .trigger('appendAnchor');
393             PMA_init_slider();
394         }) // end $.post()
395     })
396     //end displayOptionsForm handler
398     /**
399      * Ajax Event handlers for Inline Editing
400      */
402     /**
403      * On click, replace the fields of current row with an input/textarea
404      * @memberOf    jQuery
405      * @name        inline_edit_start
406      * @see         PMA_ajaxShowMessage()
407      * @see         getFieldName()
408      */
409     $(".inline_edit_anchor").live('click', function(event) {
410         /** @lends jQuery */
411         event.preventDefault();
412         $(this).removeClass('inline_edit_anchor').addClass('inline_edit_active');
414         // adding submit and hide buttons to inline edit <td>
415         // for "hide", button the original data to be restored is present in .original_data
416         // looping through all columns or rows, to find the required data and then storing it in an array.
418         var $this_children = $(this).children('span.nowrap').children('a').children('span.nowrap');
419         if (disp_mode != 'vertical'){
420             $this_children.empty();
421             $this_children.text("submit");
422         } else {
423            // vertical 
424             data_vt = $this_children.html();
425             $this_children.text("submit");
426         }
427        
428         if (disp_mode != 'vertical'){
429             $(this).append('<br/><br/><a id="hide">hide</a>');
430             $('#table_results tbody tr td a#hide').click(function(){
431                 $this_children = $(this).siblings('span.nowrap').children('a').children('span.nowrap');
432                 $this_children.empty();
433                 $this_children.text("Inline Edit");
434                 var $this_hide = $(this).parent();
435                 $this_hide.removeClass("inline_edit_active hover").addClass("inline_edit_anchor");
436                 var last_column = $this_hide.siblings().length;
437                 var txt=[];
438                 for(var i=4; i < last_column; i++){
439                     txt[i-4] = $this_hide.siblings("td:eq(" + i + ")").children(' .original_data').text();
440                 }
441                 for (var i=4; i < last_column; i++){
442                     $this_hide.siblings("td:eq(" + i + ")").empty();
443                     $this_hide.siblings("td:eq(" + i + ")").append(txt[i-4]);
444                 }
445                 $(this).prev().prev().remove();
446                 $(this).prev().remove();
447                 $(this).remove();
448                 });
449         } else {
450             var txt=[];
451             var rows=$(this).parent().siblings().length;;
453             $(this).append('<br/><br/><a id="hide">hide</a>');
454             $('#table_results tbody tr td a#hide').click(function(){
455                   
456                     var pos=$(this).parent().index();
457                     var $chg_submit=$(this).parent().children('span.nowrap').children('a').children('span.nowrap');
458                     $chg_submit.empty();
459                     $chg_submit.append(data_vt);
460                     
461                     var $this_row=$(this).parent().parent();
462                     //alert(pos);
463                     if(parseInt(pos)%2==0){
464                         $this_row.siblings("tr:eq(3) td:eq(" + pos + ")").removeClass("odd edit_row_anchor row_" + pos + " vpointer vmarker inline_edit_active").addClass("odd edit_row_anchor row_" + pos + " vpointer vmarker inline_edit_anchor");
466                         $this_row.siblings("tr:eq(3) td:eq(" + pos + ")").removeClass("odd edit_row_anchor row_" + pos + " vpointer vmarker inline_edit_active hover").addClass("odd edit_row_anchor row_" + pos + " vpointer vmarker inline_edit_anchor");
467                     } else {
468                         $this_row.siblings("tr:eq(3) td:eq(" + pos + ")").removeClass("even edit_row_anchor row_" + pos + " vpointer vmarker inline_edit_active").addClass("even edit_row_anchor row_" + pos + " vpointer vmarker inline_edit_anchor");
470                         $this_row.siblings("tr:eq(3) td:eq(" + pos + ")").removeClass("even edit_row_anchor row_" + pos + " vpointer vmarker inline_edit_active hover").addClass("even edit_row_anchor row_" + pos + " vpointer vmarker inline_edit_anchor");
472                     }
474                     for( var i=6;i<=rows+2;i++){
475                          txt[i-6]=$this_row.siblings("tr:eq("+i+") td:eq("+pos+") span.original_data").text();
476                     }
477                     for (var i=6;i<=rows+2;i++){ 
478                          $this_row.siblings("tr:eq("+i+") td:eq("+pos+")").empty();
479                          $this_row.siblings("tr:eq("+i+") td:eq("+pos+")").append(txt[i-6]);
480                     }
481                     $(this).prev().remove();
482                     $(this).prev().remove();
483                     $(this).remove();
484                         
485                     });
486         }
488         // Initialize some variables
489         if(disp_mode == 'vertical') {
490             /**
491              * @var this_row_index  Index of the current <td> in the parent <tr>
492              *                      Current <td> is the inline edit anchor.
493              */
494             var this_row_index = $(this).index();
495             /**
496              * @var $input_siblings  Object referring to all inline editable events from same row
497              */
498             var $input_siblings = $(this).parents('tbody').find('tr').find('.inline_edit:nth('+this_row_index+')');
499             /**
500              * @var where_clause    String containing the WHERE clause to select this row
501              */
502             var where_clause = $(this).parents('tbody').find('tr').find('.where_clause:nth('+this_row_index+')').val();
503         }
504         // horizontal mode
505         else {
506             var this_row_index = $(this).parent().index();
507             var $input_siblings = $(this).parent('tr').find('.inline_edit');
508             var where_clause = $(this).parent('tr').find('.where_clause').val();
509         }
511         $input_siblings.each(function() {
512             /** @lends jQuery */
513             /**
514              * @var data_value  Current value of this field
515              */
516             var data_value = $(this).html();
518             // We need to retrieve the value from the server for truncated/relation fields
519             // Find the field name
521             /**
522              * @var this_field  Object referring to this field (<td>)
523              */
524             var $this_field = $(this);
525             /**
526              * @var field_name  String containing the name of this field.
527              * @see getFieldName()
528              */
529             var field_name = getFieldName($this_field, disp_mode);
530             /**
531              * @var relation_curr_value String current value of the field (for fields that are foreign keyed).
532              */
533             var relation_curr_value = $this_field.find('a').text();
534             /**
535              * @var curr_value String current value of the field (for fields that are of type enum or set).
536              */
537             var curr_value = $this_field.text();
539             if($this_field.is(':not(.not_null)')){
540                 // add a checkbox to mark null for all the field that are nullable.
541                 $this_field.html('<div class="null_div">Null :<input type="checkbox" class="checkbox_null_'+ field_name + '_' + this_row_index +'"></div>');
542                 // check the 'checkbox_null_<field_name>_<row_index>' if the corresponding value is null
543                 if($this_field.is('.null')) {
544                     $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', true);
545                 }
547                 // if the select/editor is changed un-check the 'checkbox_null_<field_name>_<row_index>'.
548                 if ($this_field.is('.enum, .set')) {
549                     $this_field.find('select').live('change', function(e) {
550                         $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
551                     })
552                 } else if ($this_field.is('.relation')) {
553                     $this_field.find('select').live('change', function(e) {
554                         $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
555                     })
556                     $this_field.find('.browse_foreign').live('click', function(e) {
557                         $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
558                     })
559                 } else {
560                     $this_field.find('textarea').live('keypress', function(e) {
561                         $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false);
562                     })
563                 }
565                 // if 'chechbox_null_<field_name>_<row_index>' is clicked empty the corresponding select/editor.
566                 $('.checkbox_null_' + field_name + '_' + this_row_index).bind('click', function(e) {
567                     if ($this_field.is('.enum')) {
568                         $this_field.find('select').attr('value', '');
569                     } else if ($this_field.is('.set')) {
570                         $this_field.find('select').find('option').each(function() {
571                             var $option = $(this);
572                             $option.attr('selected', false);
573                         })
574                     } else if ($this_field.is('.relation')) {
575                         // if the dropdown is there to select the foreign value
576                         if ($this_field.find('select').length > 0) {
577                             $this_field.find('select').attr('value', '');
578                         // if foriegn value is selected by browsing foreing values
579                         } else {
580                             $this_field.find('span.curr_value').empty();
581                         }
582                     } else {
583                         $this_field.find('textarea').val('');
584                     }
585                 })
587             } else {
588                 $this_field.html('<div class="null_div"></div>');
589             }
591             // In each input sibling, wrap the current value in a textarea
592             // and store the current value in a hidden span
593             if($this_field.is(':not(.truncated, .transformed, .relation, .enum, .set, .null)')) {
594                 // handle non-truncated, non-transformed, non-relation values
595                 // We don't need to get any more data, just wrap the value
596                 $this_field.append('<textarea>'+data_value+'</textarea>');
597                 $this_field.append('<span class="original_data">'+data_value+'</span>');
598                 $(".original_data").hide();
599             }
600             else if($this_field.is('.truncated, .transformed')) {
601                 /** @lends jQuery */
602                 //handle truncated/transformed values values
604                 /**
605                  * @var sql_query   String containing the SQL query used to retrieve value of truncated/transformed data
606                  */
607                 var sql_query = 'SELECT ' + field_name + ' FROM ' + window.parent.table + ' WHERE ' + where_clause;
609                 // Make the Ajax call and get the data, wrap it and insert it
610                 $.post('sql.php', {
611                     'token' : window.parent.token,
612                     'db' : window.parent.db,
613                     'ajax_request' : true,
614                     'sql_query' : sql_query,
615                     'inline_edit' : true
616                 }, function(data) {
617                     if(data.success == true) {
618                         $this_field.append('<textarea>'+data.value+'</textarea>');
619                         $this_field.append('<span class="original_data">'+data_value+'</span>');
620                         $(".original_data").hide();
621                     }
622                     else {
623                         PMA_ajaxShowMessage(data.error);
624                     }
625                 }) // end $.post()
626             }
627             else if($this_field.is('.relation')) {
628                 /** @lends jQuery */
629                 //handle relations
631                 /**
632                  * @var post_params Object containing parameters for the POST request
633                  */
634                 var post_params = {
635                         'ajax_request' : true,
636                         'get_relational_values' : true,
637                         'db' : window.parent.db,
638                         'table' : window.parent.table,
639                         'column' : field_name,
640                         'token' : window.parent.token,
641                         'curr_value' : relation_curr_value
642                 }
644                 $.post('sql.php', post_params, function(data) {
645                     $this_field.append(data.dropdown);
646                     $this_field.append('<span class="original_data">'+data_value+'</span>');
647                     $(".original_data").hide();
648                 }) // end $.post()
649             }
650             else if($this_field.is('.enum')) {
651                 /** @lends jQuery */
652                 //handle enum fields
654                 /**
655                  * @var post_params Object containing parameters for the POST request
656                  */
657                 var post_params = {
658                         'ajax_request' : true,
659                         'get_enum_values' : true,
660                         'db' : window.parent.db,
661                         'table' : window.parent.table,
662                         'column' : field_name,
663                         'token' : window.parent.token,
664                         'curr_value' : curr_value
665                 }
667                 $.post('sql.php', post_params, function(data) {
668                     $this_field.append(data.dropdown);
669                     $this_field.append('<span class="original_data">'+data_value+'</span>');
670                     $(".original_data").hide();
671                 }) // end $.post()
672             }
673             else if($this_field.is('.set')) {
674                 /** @lends jQuery */
675                 //handle set fields
677                 /**
678                  * @var post_params Object containing parameters for the POST request
679                  */
680                 var post_params = {
681                         'ajax_request' : true,
682                         'get_set_values' : true,
683                         'db' : window.parent.db,
684                         'table' : window.parent.table,
685                         'column' : field_name,
686                         'token' : window.parent.token,
687                         'curr_value' : curr_value
688                 }
690                 $.post('sql.php', post_params, function(data) {
691                     $this_field.append(data.select);
692                     $this_field.append('<span class="original_data">'+data_value+'</span>');
693                     $(".original_data").hide();
694                 }) // end $.post()
695             }
696             else if($this_field.is('.null')) {
697                 //handle null fields
698                 $this_field.append('<textarea></textarea>');
699                 $this_field.append('<span class="original_data">NULL</span>');
700                 $(".original_data").hide();
701             }
702         })
703     }) // End On click, replace the current field with an input/textarea
705     /**
706      * After editing, clicking again should post data
707      *
708      * @memberOf    jQuery
709      * @name        inline_edit_save
710      * @see         PMA_ajaxShowMessage()
711      * @see         getFieldName()
712      */
713     $(".inline_edit_active span a").live('click', function(event) {
714         /** @lends jQuery */
716         event.preventDefault();
718         /**
719          * @var $this_td    Object referring to the td containing the
720          * "Inline Edit" link that was clicked to save the row that is
721          * being edited
722          *
723          */
724         var $this_td = $(this).parent().parent();
725         var $test_element = ''; // to test the presence of a element
727         // Initialize variables
728         if(disp_mode == 'vertical') {
729             /**
730              * @var this_td_index  Index of the current <td> in the parent <tr>
731              *                      Current <td> is the inline edit anchor.
732              */
733             var this_td_index = $this_td.index();
734             /**
735              * @var $input_siblings  Object referring to all inline editable events from same row
736              */
737             var $input_siblings = $this_td.parents('tbody').find('tr').find('.inline_edit:nth('+this_td_index+')');
738             /**
739              * @var where_clause    String containing the WHERE clause to select this row
740              */
741             var where_clause = $this_td.parents('tbody').find('tr').find('.where_clause:nth('+this_td_index+')').val();
742         } else {
743             var $input_siblings = $this_td.parent('tr').find('.inline_edit');
744             var where_clause = $this_td.parent('tr').find('.where_clause').val();
745         }
747         /**
748          * @var nonunique   Boolean, whether this row is unique or not
749          */
750         if($this_td.is('.nonunique')) {
751             var nonunique = 0;
752         }
753         else {
754             var nonunique = 1;
755         }
757         // Collect values of all fields to submit, we don't know which changed
758         /**
759          * @var relation_fields Array containing the name/value pairs of relational fields
760          */
761         var relation_fields = {};
762         /**
763          * @var transform_fields    Array containing the name/value pairs for transformed fields
764          */
765         var transform_fields = {};
766         /**
767          * @var transformation_fields   Boolean, if there are any transformed fields in this row
768          */
769         var transformation_fields = false;
771         /**
772          * @var sql_query String containing the SQL query to update this row
773          */
774         var sql_query = 'UPDATE ' + window.parent.table + ' SET ';
776         $input_siblings.each(function() {
777             /** @lends jQuery */
778             /**
779              * @var this_field  Object referring to this field (<td>)
780              */
781                 var $this_field = $(this);
782             /**
783              * @var field_name  String containing the name of this field.
784              * @see getFieldName()
785              */
786             var field_name = getFieldName($this_field, disp_mode);
788             /**
789              * @var this_field_params   Array temporary storage for the name/value of current field
790              */
791             var this_field_params = {};
793             if($this_field.is('.transformed')) {
794                 transformation_fields =  true;
795             }
796             /**
797              * @var is_null String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked.
798              */
799             var is_null = $this_field.find('input:checkbox').is(':checked');
800             var value;
802             if (is_null) {
803                 sql_query += ' ' + field_name + "=NULL , ";
804             } else {
805                 if($this_field.is(":not(.relation, .enum, .set)")) {
806                     this_field_params[field_name] = $this_field.find('textarea').val();
807                     if($this_field.is('.transformed')) {
808                         $.extend(transform_fields, this_field_params);
809                     }
810                 } else if ($this_field.is('.set')) {
811                     $test_element = $this_field.find('select');
812                     this_field_params[field_name] = $test_element.map(function(){
813                         return $(this).val();
814                     }).get().join(",");
815                 } else {
816                     // results from a drop-down
817                     $test_element = $this_field.find('select');
818                     if ($test_element.length != 0) {
819                         this_field_params[field_name] = $test_element.val();
820                     }
822                     // results from Browse foreign value
823                     $test_element = $this_field.find('span.curr_value');
824                     if ($test_element.length != 0) {
825                         this_field_params[field_name] = $test_element.text();
826                     }
828                     if($this_field.is('.relation')) {
829                         $.extend(relation_fields, this_field_params);
830                     }
831                 }
832                 sql_query += ' ' + field_name + "='" + this_field_params[field_name].replace(/'/g, "''") + "' , ";
833             }
834         })
836         //Remove the last ',' appended in the above loop
837         sql_query = sql_query.replace(/,\s$/, '');
838         sql_query += ' WHERE ' + PMA_urldecode(where_clause);
840         /**
841          * @var rel_fields_list  String, url encoded representation of {@link relations_fields}
842          */
843         var rel_fields_list = $.param(relation_fields);
845         /**
846          * @var transform_fields_list  String, url encoded representation of {@link transform_fields}
847          */
848         var transform_fields_list = $.param(transform_fields);
850         // Make the Ajax post after setting all parameters
851         /**
852          * @var post_params Object containing parameters for the POST request
853          */
854         var post_params = {'ajax_request' : true,
855                             'sql_query' : sql_query,
856                             'disp_direction' : disp_mode,
857                             'token' : window.parent.token,
858                             'db' : window.parent.db,
859                             'table' : window.parent.table,
860                             'clause_is_unique' : nonunique,
861                             'where_clause' : where_clause,
862                             'rel_fields_list' : rel_fields_list,
863                             'do_transformations' : transformation_fields,
864                             'transform_fields_list' : transform_fields_list,
865                             'goto' : 'sql.php',
866                             'submit_type' : 'save'
867                           };
869         // if inline_edit is successful, we need to go back to default view
870          var $del_hide=$(this).parent();
871          var $chg_submit=$(this);
873         $.post('tbl_replace.php', post_params, function(data) {
874             if(data.success == true) {
875                 // deleting the hide button if my query was successful
876                 // remove <br><br><a> tags 
877                  for ( var i=0;i<=2;i++) { $del_hide.next().remove(); }
878                  if(disp_mode!='vertical'){
879                      $chg_submit.empty();
880                      $chg_submit.text("Inline Edit");
881                  }
882                  else {
883                      $chg_submit.children('span.nowrap').empty();
884                      $chg_submit.children('span.nowrap').append(data_vt);
885                  }
887                 PMA_ajaxShowMessage(data.message);
888                 $this_td.removeClass('inline_edit_active').addClass('inline_edit_anchor');
890                 $input_siblings.each(function() {
891                     // Inline edit post has been successful.
892                     $this_sibling = $(this);
894                     var is_null = $this_sibling.find('input:checkbox').is(':checked');
895                     if (is_null) {
896                         $this_sibling.html('NULL');
897                         $this_sibling.addClass('null');
898                     } else {
899                         $this_sibling.removeClass('null');
900                         if($this_sibling.is(':not(.relation, .enum, .set)')) {
901                             /**
902                              * @var new_html    String containing value of the data field after edit
903                              */
904                             var new_html = $this_sibling.find('textarea').val();
906                             if($this_sibling.is('.transformed')) {
907                                 var field_name = getFieldName($this_sibling, disp_mode);
908                                 $.each(data.transformations, function(key, value) {
909                                     if(key == field_name) {
910                                         if($this_sibling.is('.text_plain, .application_octetstream')) {
911                                             new_html = value;
912                                             return false;
913                                         }
914                                         else {
915                                             var new_value = $this_sibling.find('textarea').val();
916                                             new_html = $(value).append(new_value);
917                                             return false;
918                                         }
919                                     }
920                                 })
921                             }
922                         }
923                         else {
924                             var new_html = '';
925                             var new_value = '';
926                             $test_element = $this_sibling.find('select');
927                             if ($test_element.length != 0) {
928                                 new_value = $test_element.val();
929                             }
931                             $test_element = $this_sibling.find('span.curr_value');
932                             if ($test_element.length != 0) {
933                                 new_value = $test_element.text();
934                             }
936                             if($this_sibling.is('.relation')) {
937                                 var field_name = getFieldName($this_sibling, disp_mode);
938                                 $.each(data.relations, function(key, value) {
939                                     if(key == field_name) {
940                                         new_html = $(value).append(new_value);
941                                         return false;
942                                     }
943                                 })
944                             } else if ($this_sibling.is('.enum')) {
945                                 new_html = new_value;
946                             } else if ($this_sibling.is('.set')) {
947                                 if (new_value != null) {
948                                     $.each(new_value, function(key, value) {
949                                         new_html = new_html + value + ',';
950                                     })
951                                     new_html = new_html.substring(0, new_html.length-1);
952                                 }
953                             }
954                         }
955                         $this_sibling.html(new_html);
956                     }
957                 })
958             }
959             else {
960                 PMA_ajaxShowMessage(data.error);
961             };
962         }) // end $.post()
963     }) // End After editing, clicking again should post data
964 }, 'top.frame_content') // end $(document).ready()
967  * Starting from some th, change the class of all td under it
968  */
969 function PMA_changeClassForColumn($this_th, newclass) {
970     // index 0 is the th containing the big T
971     var th_index = $this_th.index();
972     // .eq() is zero-based
973     th_index--;
974     var $tr_with_data = $this_th.closest('table').find('tbody tr ').has('td.data');
975     $tr_with_data.each(function() {
976         $(this).find('td.data:eq('+th_index+')').toggleClass(newclass);
977     });
980 $(document).ready(function() {
982     $('.browse_foreign').live('click', function(e) {
983         e.preventDefault();
984         window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes,resizable=yes');
985         $anchor = $(this);
986         $anchor.addClass('browse_foreign_clicked');
987         return false;
988     });
990     /**
991      * vertical column highlighting in horizontal mode when hovering over the column header
992      */
993     $('.column_heading').live('hover', function() {
994         PMA_changeClassForColumn($(this), 'hover');
995         });
997     /**
998      * vertical column marking in horizontal mode when clicking the column header
999      */
1000     $('.column_heading').live('click', function() {
1001         PMA_changeClassForColumn($(this), 'marked');
1002         });
1005 /**#@- */