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'));
22 * Get the field name for the current field. Required to construct the query
25 * @param $this_field jQuery object that points to the current field's tr
26 * @param disp_mode string
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();
38 var this_field_index
= $this_field
.index();
39 // ltr or rtl direction does not impact how the DOM was generated
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();
49 field_name
= $.trim(field_name
);
55 * The function that iterates over each row in the table_results and appends a
56 * new inline edit anchor to each table row.
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
);
79 .addClass('inline_edit_anchor')
80 .find('a').attr('href', '#')
82 .text(' ' + PMA_messages
['strInlineEdit'])
83 .prepend($img_object
);
85 $cloned_tr
.insertAfter($this_tr
);
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');
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
);
109 .find('a').attr('href', '#')
111 .text(' ' + PMA_messages
['strInlineEdit']);
115 .prepend($img_object
);
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
);
122 .find('.clickprevimage')
123 .text(' ' + PMA_messages
['strInlineEdit']);
127 .addClass('inline_edit_anchor');
129 $this_td
.after($cloned_anchor
);
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');
146 * @description <p>Ajax scripts for sql and browse pages</p>
148 * Actions ajaxified here:
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>
157 * @name document.ready
160 $(document
).ready(function() {
163 * Set a parameter for all Ajax queries made on this page. Don't let the
164 * web server serve cached pages
171 * current value of the direction in which the table is displayed
176 var disp_mode
= $("#top_direction_dropdown").val();
179 * Update value of {@link jQuery.disp_mode} everytime the direction dropdown changes value
181 * @name direction_dropdown_change
183 $("#top_direction_dropdown, #bottom_direction_dropdown").live('change', function(event
) {
184 disp_mode
= $(this).val();
188 * Attach the {@link appendInlineAnchor} function to a custom event, which
189 * will be triggered manually everytime the table of results is reloaded
192 $("#sqlqueryresults").live('appendAnchor',function() {
193 appendInlineAnchor();
197 * Trigger the appendAnchor event to prepare the first table for inline edit
198 * (see $GLOBALS['cfg']['AjaxEnable'])
200 * @name sqlqueryresults_trigger
202 $("#sqlqueryresults.ajax").trigger('appendAnchor');
205 * Append the "Show/Hide query box" message to the query input form
208 * @name appendToggleSpan
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
219 // Attach the toggling of the query box visibility to a click
220 $("#togglequerybox").bind('click', function() {
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" />');
230 $link
.text(PMA_messages
['strHideQueryBox']);
232 // avoid default click action
238 * Ajax Event handler for 'SQL Query Submit'
240 * @see PMA_ajaxShowMessage()
241 * @see $cfg['AjaxEnable']
243 * @name sqlqueryform_submit
245 $("#sqlqueryform.ajax").live('submit', function(event
) {
246 event
.preventDefault();
247 // remove any div containing a previous error message
248 $('.error').remove();
251 var $msgbox
= 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" />');
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
282 else if (data
.success
== false ) {
283 // show an error message that stays on screen
284 $('#sqlqueryform').before(data
.error
);
285 $('#sqlqueryresults').hide();
288 // real results are returned
289 $received_data
= $(data
);
290 $zero_row_results
= $received_data
.find('textarea[name="sql_query"]');
291 // if zero rows are returned from the query execution
292 if ($zero_row_results
.length
> 0) {
293 $('#sqlquery').val($zero_row_results
.val());
295 $('#sqlqueryresults').show();
296 $("#sqlqueryresults").html(data
);
297 $("#sqlqueryresults").trigger('appendAnchor');
298 $('#togglequerybox').show();
299 if($("#togglequerybox").siblings(":visible").length
> 0) {
300 $("#togglequerybox").trigger('click');
305 PMA_ajaxRemoveMessage($msgbox
);
308 }) // end SQL Query submit
311 * Ajax Event handlers for Paginating the results table
315 * Paginate when we click any of the navigation buttons
316 * (only if the element has the ajax class, see $cfg['AjaxEnable'])
318 * @name paginate_nav_button_click
319 * @uses PMA_ajaxShowMessage()
320 * @see $cfg['AjaxEnable']
322 $("input[name=navig].ajax").live('click', function(event
) {
324 event
.preventDefault();
326 var $msgbox
= PMA_ajaxShowMessage();
329 * @var $the_form Object referring to the form element that paginates the results table
331 var $the_form
= $(this).parent("form");
333 $the_form
.append('<input type="hidden" name="ajax_request" value="true" />');
335 $.post($the_form
.attr('action'), $the_form
.serialize(), function(data
) {
336 $("#sqlqueryresults").html(data
);
337 $("#sqlqueryresults").trigger('appendAnchor');
340 PMA_ajaxRemoveMessage($msgbox
);
342 })// end Paginate results table
345 * Paginate results with Page Selector dropdown
347 * @name paginate_dropdown_change
348 * @see $cfg['AjaxEnable']
350 $("#pageselector").live('change', function(event
) {
351 var $the_form
= $(this).parent("form");
353 if ($(this).hasClass('ajax')) {
354 event
.preventDefault();
356 var $msgbox
= PMA_ajaxShowMessage();
358 $.post($the_form
.attr('action'), $the_form
.serialize() + '&ajax_request=true', function(data
) {
359 $("#sqlqueryresults").html(data
);
360 $("#sqlqueryresults").trigger('appendAnchor');
362 PMA_ajaxRemoveMessage($msgbox
);
368 })// end Paginate results with Page Selector
371 * Ajax Event handler for sorting the results table
373 * @name table_results_sort_click
374 * @see $cfg['AjaxEnable']
376 $("#table_results.ajax").find("a[title=Sort]").live('click', function(event
) {
377 event
.preventDefault();
379 var $msgbox
= PMA_ajaxShowMessage();
383 $.get($anchor
.attr('href'), $anchor
.serialize() + '&ajax_request=true', function(data
) {
384 $("#sqlqueryresults")
386 .trigger('appendAnchor');
387 PMA_ajaxRemoveMessage($msgbox
);
389 })//end Sort results table
392 * Ajax Event handler for the display options
394 * @name displayOptionsForm_submit
395 * @see $cfg['AjaxEnable']
397 $("#displayOptionsForm.ajax").live('submit', function(event
) {
398 event
.preventDefault();
402 $.post($form
.attr('action'), $form
.serialize() + '&ajax_request=true' , function(data
) {
403 $("#sqlqueryresults")
405 .trigger('appendAnchor');
409 //end displayOptionsForm handler
412 * Ajax Event handlers for Inline Editing
416 * On click, replace the fields of current row with an input/textarea
418 * @name inline_edit_start
419 * @see PMA_ajaxShowMessage()
420 * @see getFieldName()
422 $(".inline_edit_anchor span a").live('click', function(event
) {
424 event
.preventDefault();
426 var $edit_td
= $(this).parents('td');
427 $edit_td
.removeClass('inline_edit_anchor').addClass('inline_edit_active').parent('tr').addClass('noclick');
429 // Adding submit and hide buttons to inline edit <td>.
430 // For "hide" button the original data to be restored is
431 // kept in the jQuery data element 'original_data' inside the <td>.
432 // Looping through all columns or rows, to find the required data and then storing it in an array.
434 var $this_children
= $edit_td
.children('span.nowrap').children('a').children('span.nowrap');
435 if (disp_mode
!= 'vertical') {
436 $this_children
.empty();
437 $this_children
.text(PMA_messages
['strSave']);
440 data_vt
= $this_children
.html();
441 $this_children
.text(PMA_messages
['strSave']);
444 var hide_link
= '<br /><br /><a id="hide">' + PMA_messages
['strHide'] + '</a>';
445 if (disp_mode
!= 'vertical') {
446 $edit_td
.append(hide_link
);
447 $('#table_results tbody tr td a#hide').click(function() {
448 $this_children
= $(this).siblings('span.nowrap').children('a').children('span.nowrap');
449 $this_children
.empty();
450 $this_children
.text(PMA_messages
['strInlineEdit']);
452 var $this_hide
= $(this).parent();
453 $this_hide
.removeClass("inline_edit_active hover").addClass("inline_edit_anchor");
454 $this_hide
.parent().removeClass("hover noclick");
455 $this_hide
.siblings().removeClass("hover");
457 var last_column
= $this_hide
.siblings().length
;
459 for(var i
= 4; i
< last_column
; i
++) {
460 if($this_hide
.siblings("td:eq(" + i
+ ")").hasClass("inline_edit") == false) {
463 txt
= $this_hide
.siblings("td:eq(" + i
+ ")").data('original_data');
464 if($this_hide
.siblings("td:eq(" + i
+ ")").children().length
!= 0) {
465 $this_hide
.siblings("td:eq(" + i
+ ")").empty();
466 $this_hide
.siblings("td:eq(" + i
+ ")").append(txt
);
469 $(this).prev().prev().remove();
470 $(this).prev().remove();
475 var rows
= $edit_td
.parent().siblings().length
;
477 $edit_td
.append(hide_link
);
478 $('#table_results tbody tr td a#hide').click(function() {
479 var pos
= $(this).parent().index();
480 var $chg_submit
= $(this).parent().children('span.nowrap').children('a').children('span.nowrap');
482 $chg_submit
.append(data_vt
);
484 var $this_row
= $(this).parents('tr');
485 // changing inline_edit_active to inline_edit_anchor
486 $this_row
.siblings("tr:eq(3) td:eq(" + pos
+ ")").removeClass("inline_edit_active").addClass("inline_edit_anchor");
488 // removing marked and hover classes.
489 $this_row
.parent('tbody').find('tr').find("td:eq(" + pos
+ ")").removeClass("marked hover");
491 for( var i
= 6; i
<= rows
+ 2; i
++){
492 if( $this_row
.siblings("tr:eq(" + i
+ ") td:eq(" + pos
+ ")").hasClass("inline_edit") == false) {
495 txt
= $this_row
.siblings("tr:eq(" + i
+ ") td:eq(" + pos
+ ")").data('original_data');
496 $this_row
.siblings("tr:eq(" + i
+ ") td:eq(" + pos
+ ")").empty();
497 $this_row
.siblings("tr:eq(" + i
+ ") td:eq(" + pos
+ ")").append(txt
);
499 $(this).prev().remove();
500 $(this).prev().remove();
505 // Initialize some variables
506 if(disp_mode
== 'vertical') {
508 * @var this_row_index Index of the current <td> in the parent <tr>
509 * Current <td> is the inline edit anchor.
511 var this_row_index
= $edit_td
.index();
513 * @var $input_siblings Object referring to all inline editable events from same row
515 var $input_siblings
= $edit_td
.parents('tbody').find('tr').find('.inline_edit:nth('+this_row_index
+')');
517 * @var where_clause String containing the WHERE clause to select this row
519 var where_clause
= $edit_td
.parents('tbody').find('tr').find('.where_clause:nth('+this_row_index
+')').val();
523 var this_row_index
= $edit_td
.parent().index();
524 var $input_siblings
= $edit_td
.parent('tr').find('.inline_edit');
525 var where_clause
= $edit_td
.parent('tr').find('.where_clause').val();
528 $input_siblings
.each(function() {
531 * @var data_value Current value of this field
533 var data_value
= $(this).html();
535 // We need to retrieve the value from the server for truncated/relation fields
536 // Find the field name
539 * @var this_field Object referring to this field (<td>)
541 var $this_field
= $(this);
543 * @var field_name String containing the name of this field.
544 * @see getFieldName()
546 var field_name
= getFieldName($this_field
, disp_mode
);
548 * @var relation_curr_value String current value of the field (for fields that are foreign keyed).
550 var relation_curr_value
= $this_field
.find('a').text();
552 * @var relation_key_or_display_column String relational key if in 'Relational display column' mode,
553 * relational display column if in 'Relational key' mode (for fields that are foreign keyed).
555 var relation_key_or_display_column
= $this_field
.find('a').attr('title');
557 * @var curr_value String current value of the field (for fields that are of type enum or set).
559 var curr_value
= $this_field
.text();
561 if($this_field
.is(':not(.not_null)')){
562 // add a checkbox to mark null for all the field that are nullable.
563 $this_field
.html('<div class="null_div">Null :<input type="checkbox" class="checkbox_null_'+ field_name
+ '_' + this_row_index
+'"></div>');
564 // check the 'checkbox_null_<field_name>_<row_index>' if the corresponding value is null
565 if($this_field
.is('.null')) {
566 $('.checkbox_null_' + field_name
+ '_' + this_row_index
).attr('checked', true);
569 // if the select/editor is changed un-check the 'checkbox_null_<field_name>_<row_index>'.
570 if ($this_field
.is('.enum, .set')) {
571 $this_field
.find('select').live('change', function(e
) {
572 $('.checkbox_null_' + field_name
+ '_' + this_row_index
).attr('checked', false);
574 } else if ($this_field
.is('.relation')) {
575 $this_field
.find('select').live('change', function(e
) {
576 $('.checkbox_null_' + field_name
+ '_' + this_row_index
).attr('checked', false);
578 $this_field
.find('.browse_foreign').live('click', function(e
) {
579 $('.checkbox_null_' + field_name
+ '_' + this_row_index
).attr('checked', false);
582 $this_field
.find('textarea').live('keypress', function(e
) {
583 $('.checkbox_null_' + field_name
+ '_' + this_row_index
).attr('checked', false);
587 // if 'checkbox_null_<field_name>_<row_index>' is clicked empty the corresponding select/editor.
588 $('.checkbox_null_' + field_name
+ '_' + this_row_index
).bind('click', function(e
) {
589 if ($this_field
.is('.enum')) {
590 $this_field
.find('select').attr('value', '');
591 } else if ($this_field
.is('.set')) {
592 $this_field
.find('select').find('option').each(function() {
593 var $option
= $(this);
594 $option
.attr('selected', false);
596 } else if ($this_field
.is('.relation')) {
597 // if the dropdown is there to select the foreign value
598 if ($this_field
.find('select').length
> 0) {
599 $this_field
.find('select').attr('value', '');
600 // if foriegn value is selected by browsing foreing values
602 $this_field
.find('span.curr_value').empty();
605 $this_field
.find('textarea').val('');
610 $this_field
.html('<div class="null_div"></div>');
613 // In each input sibling, wrap the current value in a textarea
614 // and store the current value in a hidden span
615 if($this_field
.is(':not(.truncated, .transformed, .relation, .enum, .set, .null)')) {
616 // handle non-truncated, non-transformed, non-relation values
617 // We don't need to get any more data, just wrap the value
618 $this_field
.append('<textarea>'+data_value
+'</textarea>');
619 $this_field
.data('original_data', data_value
);
621 else if($this_field
.is('.truncated, .transformed')) {
623 //handle truncated/transformed values values
626 * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data
628 var sql_query
= 'SELECT `' + field_name
+ '` FROM `' + window
.parent
.table
+ '` WHERE ' + PMA_urldecode(where_clause
);
630 // Make the Ajax call and get the data, wrap it and insert it
632 'token' : window
.parent
.token
,
633 'db' : window
.parent
.db
,
634 'ajax_request' : true,
635 'sql_query' : sql_query
,
638 if(data
.success
== true) {
639 $this_field
.append('<textarea>'+data
.value
+'</textarea>');
640 $this_field
.data('original_data', data_value
);
643 PMA_ajaxShowMessage(data
.error
);
647 else if($this_field
.is('.relation')) {
652 * @var post_params Object containing parameters for the POST request
655 'ajax_request' : true,
656 'get_relational_values' : true,
657 'db' : window
.parent
.db
,
658 'table' : window
.parent
.table
,
659 'column' : field_name
,
660 'token' : window
.parent
.token
,
661 'curr_value' : relation_curr_value
,
662 'relation_key_or_display_column' : relation_key_or_display_column
665 $.post('sql.php', post_params
, function(data
) {
666 $this_field
.append(data
.dropdown
);
667 $this_field
.data('original_data', data_value
);
670 else if($this_field
.is('.enum')) {
675 * @var post_params Object containing parameters for the POST request
678 'ajax_request' : true,
679 'get_enum_values' : true,
680 'db' : window
.parent
.db
,
681 'table' : window
.parent
.table
,
682 'column' : field_name
,
683 'token' : window
.parent
.token
,
684 'curr_value' : curr_value
687 $.post('sql.php', post_params
, function(data
) {
688 $this_field
.append(data
.dropdown
);
689 $this_field
.data('original_data', data_value
);
692 else if($this_field
.is('.set')) {
697 * @var post_params Object containing parameters for the POST request
700 'ajax_request' : true,
701 'get_set_values' : true,
702 'db' : window
.parent
.db
,
703 'table' : window
.parent
.table
,
704 'column' : field_name
,
705 'token' : window
.parent
.token
,
706 'curr_value' : curr_value
709 $.post('sql.php', post_params
, function(data
) {
710 $this_field
.append(data
.select
);
711 $this_field
.data('original_data', data_value
);
714 else if($this_field
.is('.null')) {
716 $this_field
.append('<textarea></textarea>');
717 $this_field
.data('original_data', 'NULL');
720 }) // End On click, replace the current field with an input/textarea
723 * After editing, clicking again should post data
726 * @name inline_edit_save
727 * @see PMA_ajaxShowMessage()
728 * @see getFieldName()
730 $(".inline_edit_active span a").live('click', function(event
) {
733 event
.preventDefault();
736 * @var $this_td Object referring to the td containing the
737 * "Inline Edit" link that was clicked to save the row that is
741 var $this_td
= $(this).parent().parent();
742 var $test_element
= ''; // to test the presence of a element
744 // Initialize variables
745 if(disp_mode
== 'vertical') {
747 * @var this_td_index Index of the current <td> in the parent <tr>
748 * Current <td> is the inline edit anchor.
750 var this_td_index
= $this_td
.index();
752 * @var $input_siblings Object referring to all inline editable events from same row
754 var $input_siblings
= $this_td
.parents('tbody').find('tr').find('.inline_edit:nth('+this_td_index
+')');
756 * @var where_clause String containing the WHERE clause to select this row
758 var where_clause
= $this_td
.parents('tbody').find('tr').find('.where_clause:nth('+this_td_index
+')').val();
760 var $input_siblings
= $this_td
.parent('tr').find('.inline_edit');
761 var where_clause
= $this_td
.parent('tr').find('.where_clause').val();
765 * @var nonunique Boolean, whether this row is unique or not
767 if($this_td
.is('.nonunique')) {
774 // Collect values of all fields to submit, we don't know which changed
776 * @var relation_fields Array containing the name/value pairs of relational fields
778 var relation_fields
= {};
780 * @var transform_fields Array containing the name/value pairs for transformed fields
782 var transform_fields
= {};
784 * @var transformation_fields Boolean, if there are any transformed fields in this row
786 var transformation_fields
= false;
789 * @var sql_query String containing the SQL query to update this row
791 var sql_query
= 'UPDATE `' + window
.parent
.table
+ '` SET ';
793 var need_to_post
= false;
795 $input_siblings
.each(function() {
798 * @var this_field Object referring to this field (<td>)
800 var $this_field
= $(this);
802 * @var field_name String containing the name of this field.
803 * @see getFieldName()
805 var field_name
= getFieldName($this_field
, disp_mode
);
808 * @var this_field_params Array temporary storage for the name/value of current field
810 var this_field_params
= {};
812 if($this_field
.is('.transformed')) {
813 transformation_fields
= true;
816 * @var is_null String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked.
818 var is_null
= $this_field
.find('input:checkbox').is(':checked');
822 sql_query
+= ' `' + field_name
+ "`=NULL , ";
825 if($this_field
.is(":not(.relation, .enum, .set)")) {
826 this_field_params
[field_name
] = $this_field
.find('textarea').val();
827 if($this_field
.is('.transformed')) {
828 $.extend(transform_fields
, this_field_params
);
830 } else if ($this_field
.is('.set')) {
831 $test_element
= $this_field
.find('select');
832 this_field_params
[field_name
] = $test_element
.map(function(){
833 return $(this).val();
836 // results from a drop-down
837 $test_element
= $this_field
.find('select');
838 if ($test_element
.length
!= 0) {
839 this_field_params
[field_name
] = $test_element
.val();
842 // results from Browse foreign value
843 $test_element
= $this_field
.find('span.curr_value');
844 if ($test_element
.length
!= 0) {
845 this_field_params
[field_name
] = $test_element
.text();
848 if($this_field
.is('.relation')) {
849 $.extend(relation_fields
, this_field_params
);
852 if (this_field_params
[field_name
] != $this_field
.data('original_data')) {
853 sql_query
+= ' `' + field_name
+ "`='" + this_field_params
[field_name
].replace(/'/g, "''") + "' , ";
859 //Remove the last ',' appended in the above loop
860 sql_query = sql_query.replace(/,\s$/, '');
861 sql_query += ' WHERE ' + PMA_urldecode(where_clause);
864 * @var rel_fields_list String, url encoded representation of {@link relations_fields}
866 var rel_fields_list = $.param(relation_fields);
869 * @var transform_fields_list String, url encoded representation of {@link transform_fields}
871 var transform_fields_list = $.param(transform_fields);
873 // if inline_edit is successful, we need to go back to default view
874 var $del_hide=$(this).parent();
875 var $chg_submit=$(this);
878 // Make the Ajax post after setting all parameters
880 * @var post_params Object containing parameters for the POST request
882 var post_params = {'ajax_request' : true,
883 'sql_query' : sql_query,
884 'disp_direction' : disp_mode,
885 'token' : window.parent.token,
886 'db' : window.parent.db,
887 'table' : window.parent.table,
888 'clause_is_unique' : nonunique,
889 'where_clause' : where_clause,
890 'rel_fields_list' : rel_fields_list,
891 'do_transformations' : transformation_fields,
892 'transform_fields_list' : transform_fields_list,
894 'submit_type' : 'save'
897 $.post('tbl_replace.php', post_params, function(data) {
898 if(data.success == true) {
899 PMA_ajaxShowMessage(data.message);
900 // remove possible previous feedback message
901 $('#result_query').remove();
902 if (typeof data.result_query != 'undefined') {
904 $('#sqlqueryresults').prepend('<div id="result_query
" align="left
"></div>');
905 $('#result_query').prepend(data.result_query);
907 PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode);
909 PMA_ajaxShowMessage(data.error);
913 // no posting was done but still need to display the row
914 // in its previous format
915 PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, '', disp_mode);
917 }) // End After editing, clicking again should post data
918 }, 'top.frame_content') // end $(document).ready()
922 * Visually put back the row in the state it was before entering Inline edit
924 * (when called in the situation where no posting was done, the data
925 * parameter is empty)
927 function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data, disp_mode) {
929 // deleting the hide button
930 // remove <br><br><a> tags
931 for ( var i = 0; i <= 2; i++) {
932 $del_hide.next().remove();
934 if(disp_mode != 'vertical'){
936 $chg_submit.html('<span class="nowrap
"></span>');
937 $chg_submit.children('span.nowrap').text(PMA_messages['strInlineEdit']);
939 $chg_submit.children('span.nowrap').empty();
940 $chg_submit.children('span.nowrap').append(data_vt);
943 // changing inline_edit_active to inline_edit_anchor
944 $this_td.removeClass('inline_edit_active').addClass('inline_edit_anchor');
946 // removing hover, marked and noclick classes
947 $this_td.parent('tr').removeClass('noclick');
948 if(disp_mode != 'vertical') {
949 $this_td.parent('tr').removeClass('hover').find('td').removeClass('hover');
951 $this_td.parents('tbody').find('tr').find('td:eq(' + $this_td.index() + ')').removeClass('marked');
954 $input_siblings.each(function() {
955 // Inline edit post has been successful.
956 $this_sibling = $(this);
958 var is_null = $this_sibling.find('input:checkbox').is(':checked');
960 $this_sibling.html('NULL');
961 $this_sibling.addClass('null');
963 $this_sibling.removeClass('null');
964 if($this_sibling.is(':not(.relation, .enum, .set)')) {
966 * @var new_html String containing value of the data field after edit
968 var new_html = $this_sibling.find('textarea').val();
970 if($this_sibling.is('.transformed')) {
971 var field_name = getFieldName($this_sibling, disp_mode);
972 if (typeof data.transformations != 'undefined') {
973 $.each(data.transformations, function(key, value) {
974 if(key == field_name) {
975 if($this_sibling.is('.text_plain, .application_octetstream')) {
979 var new_value = $this_sibling.find('textarea').val();
980 new_html = $(value).append(new_value);
990 $test_element = $this_sibling.find('select');
991 if ($test_element.length != 0) {
992 new_value = $test_element.val();
994 $test_element = $this_sibling.find('span.curr_value');
995 if ($test_element.length != 0) {
996 new_value = $test_element.text();
999 if($this_sibling.is('.relation')) {
1000 var field_name = getFieldName($this_sibling, disp_mode);
1001 if (typeof data.relations != 'undefined') {
1002 $.each(data.relations, function(key, value) {
1003 if(key == field_name) {
1004 new_html = $(value).append(new_value);
1009 } else if ($this_sibling.is('.enum')) {
1010 new_html = new_value;
1011 } else if ($this_sibling.is('.set')) {
1012 if (new_value != null) {
1013 $.each(new_value, function(key, value) {
1014 new_html = new_html + value + ',';
1016 new_html = new_html.substring(0, new_html.length-1);
1020 $this_sibling.html(new_html);
1026 * Starting from some th, change the class of all td under it
1028 function PMA_changeClassForColumn($this_th, newclass) {
1029 // index 0 is the th containing the big T
1030 var th_index = $this_th.index();
1031 // .eq() is zero-based
1033 var $tds = $this_th.closest('table').find('tbody tr').find('td.data:eq('+th_index+')');
1034 if ($this_th.data('has_class_'+newclass)) {
1035 $tds.removeClass(newclass);
1036 $this_th.data('has_class_'+newclass, false);
1038 $tds.addClass(newclass);
1039 $this_th.data('has_class_'+newclass, true);
1043 $(document).ready(function() {
1045 $('.browse_foreign').live('click', function(e) {
1047 window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes,resizable=yes');
1049 $anchor.addClass('browse_foreign_clicked');
1054 * vertical column highlighting in horizontal mode when hovering over the column header
1056 $('.column_heading').live('hover', function() {
1057 PMA_changeClassForColumn($(this), 'hover');
1061 * vertical column marking in horizontal mode when clicking the column header
1063 $('.column_heading').live('click', function() {
1064 PMA_changeClassForColumn($(this), 'marked');