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 * Get the field name for the current field. Required to construct the query
14 * @param this_field_obj jQuery object that points to the current field's tr
15 * @param disp_mode string
17 function getFieldName(this_field_obj, disp_mode) {
19 if(disp_mode == 'vertical') {
20 var field_name = $(this_field_obj).siblings('th').find('a').text();
23 var this_field_index = $(this_field_obj).index();
24 if(window.parent.text_dir == 'ltr') {
25 // 4 columns to account for the checkbox, edit, delete and appended inline edit anchors
26 var field_name = $(this_field_obj).parents('table').find('thead').find('th:nth('+ (this_field_index-4 )+') a').text();
29 var field_name = $(this_field_obj).parents('table').find('thead').find('th:nth('+ this_field_index+') a').text();
33 field_name = $.trim(field_name);
39 * The function that iterates over each row in the table_results and appends a
40 * new inline edit anchor to each table row.
42 * @param disp_mode string
44 function appendInlineAnchor(disp_mode) {
45 if(disp_mode == 'vertical') {
46 var cloned_row = $('.edit_row_anchor').removeClass('edit_row_anchor').parent('tr').clone();
48 var img_object = $(cloned_row).find('img:first').attr('title', PMA_messages['strInlineEdit']);
50 $(cloned_row).find('td').addClass('edit_row_anchor')
51 .find('a').attr('href', '#')
53 .text(PMA_messages['strInlineEdit'])
56 $(cloned_row).insertBefore($('.where_clause').parent('tr'));
58 $("#table_results").find('tr:first').find('th')
59 .attr('rowspan', '4');
62 $('.edit_row_anchor').each(function() {
64 $(this).removeClass('edit_row_anchor');
66 var cloned_anchor = $(this).clone();
68 var img_object = $(cloned_anchor).find('img').attr('title', PMA_messages['strInlineEdit']);
70 $(cloned_anchor).addClass('edit_row_anchor')
71 .find('a').attr('href', '#')
73 .text(PMA_messages['strInlineEdit'])
76 $(this).siblings('.where_clause')
77 .before(cloned_anchor);
80 $('#rowsDeleteForm').find('thead').find('th').each(function() {
81 if($(this).attr('colspan') == 3) {
82 $(this).attr('colspan', '4')
93 * @description <p>Ajax scripts for sql and browse pages</p>
95 * Actions ajaxified here:
97 * <li>Retrieve results of an SQL query</li>
98 * <li>Paginate the results table</li>
99 * <li>Sort the results table</li>
100 * <li>Change table according to display options</li>
101 * <li>Inline editing of data</li>
104 * @name document.ready
107 $(document).ready(function() {
110 * Set a parameter for all Ajax queries made on this page. Don't let the
111 * web server serve cached pages
118 * current value of the direction in which the table is displayed
123 var disp_mode = $("#top_direction_dropdown").val();
126 * Update value of {@link jQuery.disp_mode} everytime the direction dropdown changes value
128 * @name direction_dropdown_change
130 $("#top_direction_dropdown, #bottom_direction_dropdown").live('change', function(event) {
131 disp_mode = $(this).val();
135 * Attach the {@link appendInlineAnchor} function to a custom event, which
136 * will be triggered manually everytime the table of results is reloaded
138 * @name sqlqueryresults_live
140 $("#sqlqueryresults").live('appendAnchor',function() {
141 appendInlineAnchor(disp_mode);
145 * Trigger the appendAnchor event to prepare the first table for inline edit
148 * @name sqlqueryresults_trigger
150 $("#sqlqueryresults").trigger('appendAnchor');
153 * Append the "Show/Hide query box" message to the query input form
156 * @name appendToggleSpan
158 // do not add this link more than once
159 if (! $('#sqlqueryform').find('a').is('#togglequerybox')) {
160 $('<a id="togglequerybox"></a>')
161 .html(PMA_messages['strHideQueryBox'])
162 .appendTo("#sqlqueryform");
164 // Attach the toggling of the query box visibility to a click
165 $("#togglequerybox").bind('click', function() {
167 $link.siblings().slideToggle("medium");
168 if ($link.text() == PMA_messages['strHideQueryBox']) {
169 $link.text(PMA_messages['strShowQueryBox']);
171 $link.text(PMA_messages['strHideQueryBox']);
173 // avoid default click action
179 * Ajax Event handler for 'SQL Query Submit'
181 * @see PMA_ajaxShowMessage()
183 * @name sqlqueryform_submit
185 $("#sqlqueryform").live('submit', function(event) {
186 event.preventDefault();
187 // remove any div containing a previous error message
188 $('.error').remove();
191 PMA_ajaxShowMessage();
193 if (! $form.find('input:hidden').is('#ajax_request_hidden')) {
194 $form.append('<input type="hidden" id="ajax_request_hidden" name="ajax_request" value="true" />');
197 $.post($(this).attr('action'), $(this).serialize() , function(data) {
198 if(data.success == true) {
199 PMA_ajaxShowMessage(data.message);
200 $('#sqlqueryresults').show();
201 // this happens if a USE command was typed
202 if (typeof data.reload != 'undefined') {
203 $form.find('input[name=db]').val(data.db);
204 // need to regenerate the whole upper part
205 $form.find('input[name=ajax_request]').remove();
206 $form.append('<input type="hidden" name="reload" value="true" />');
207 $.post('db_sql.php', $form.serialize(), function(data) {
208 $('body').html(data);
209 }); // end inner post
212 else if (data.success == false ) {
213 // show an error message that stays on screen
214 $('#sqlqueryform').before(data.error);
215 $('#sqlqueryresults').hide();
218 $('#sqlqueryresults').show();
219 $("#sqlqueryresults").html(data);
220 $("#sqlqueryresults").trigger('appendAnchor');
221 if($("#togglequerybox").siblings(":visible").length > 0) {
222 $("#togglequerybox").trigger('click');
226 }) // end SQL Query submit
229 * Ajax Event handlers for Paginating the results table
233 * Paginate when we click any of the navigation buttons
235 * @name paginate_nav_button_click
236 * @uses PMA_ajaxShowMessage()
238 $("input[name=navig]").live('click', function(event) {
240 event.preventDefault();
242 PMA_ajaxShowMessage();
245 * @var the_form Object referring to the form element that paginates the results table
247 var the_form = $(this).parent("form");
249 $(the_form).append('<input type="hidden" name="ajax_request" value="true" />');
251 $.post($(the_form).attr('action'), $(the_form).serialize(), function(data) {
252 $("#sqlqueryresults").html(data);
253 $("#sqlqueryresults").trigger('appendAnchor');
255 })// end Paginate results table
258 * Paginate results with Page Selector dropdown
260 * @name paginate_dropdown_change
262 $("#pageselector").live('change', function(event) {
263 event.preventDefault();
265 PMA_ajaxShowMessage();
267 $.get($(this).attr('href'), $(this).serialize() + '&ajax_request=true', function(data) {
268 $("#sqlqueryresults").html(data);
269 $("#sqlqueryresults").trigger('appendAnchor');
271 })// end Paginate results with Page Selector
274 * Ajax Event handler for sorting the results table
276 * @name table_results_sort_click
278 $("#table_results").find("a[title=Sort]").live('click', function(event) {
279 event.preventDefault();
281 PMA_ajaxShowMessage();
283 $.get($(this).attr('href'), $(this).serialize() + '&ajax_request=true', function(data) {
284 $("#sqlqueryresults").html(data);
285 $("#sqlqueryresults").trigger('appendAnchor');
287 })//end Sort results table
290 * Ajax Event handler for the display options
292 * @name displayOptionsForm_submit
294 $("#displayOptionsForm").live('submit', function(event) {
295 event.preventDefault();
297 $.post($(this).attr('action'), $(this).serialize() + '&ajax_request=true' , function(data) {
298 $("#sqlqueryresults").html(data);
299 $("#sqlqueryresults").trigger('appendAnchor');
302 //end displayOptionsForm handler
305 * Ajax Event handlers for Inline Editing
309 * On click, replace the current field with an input/textarea
311 * @name inline_edit_start
312 * @see PMA_ajaxShowMessage()
313 * @see getFieldName()
315 $(".edit_row_anchor").live('click', function(event) {
317 event.preventDefault();
319 $(this).removeClass('edit_row_anchor').addClass('edit_row_anchor_active');
321 // Initialize some variables
322 if(disp_mode == 'vertical') {
324 * @var this_row_index Index of the current <td> in the parent <tr>
325 * Current <td> is the inline edit anchor.
327 var this_row_index = $(this).index();
329 * @var input_siblings Object referring to all inline editable events from same row
331 var input_siblings = $(this).parents('tbody').find('tr').find('.data_inline_edit:nth('+this_row_index+')');
333 * @var where_clause String containing the WHERE clause to select this row
335 var where_clause = $(this).parents('tbody').find('tr').find('.where_clause:nth('+this_row_index+')').val();
338 var input_siblings = $(this).parent('tr').find('.data_inline_edit');
339 var where_clause = $(this).parent('tr').find('.where_clause').val();
342 $(input_siblings).each(function() {
345 * @var data_value Current value of this field
347 var data_value = $(this).html();
349 // We need to retrieve the value from the server for truncated/relation fields
350 // Find the field name
353 * @var this_field Object referring to this field (<td>)
355 var this_field = $(this);
357 * @var field_name String containing the name of this field.
358 * @see getFieldName()
360 var field_name = getFieldName($(this), disp_mode);
362 // In each input sibling, wrap the current value in a textarea
363 // and store the current value in a hidden span
364 if($(this).is(':not(.truncated, .transformed, .relation, .enum, .null)')) {
365 // handle non-truncated, non-transformed, non-relation values
366 // We don't need to get any more data, just wrap the value
367 $(this).html('<textarea>'+data_value+'</textarea>')
368 .append('<span class="original_data">'+data_value+'</span>');
369 $(".original_data").hide();
371 else if($(this).is('.truncated, .transformed')) {
373 //handle truncated/transformed values values
376 * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data
378 var sql_query = 'SELECT ' + field_name + ' FROM ' + window.parent.table + ' WHERE ' + where_clause;
380 // Make the Ajax call and get the data, wrap it and insert it
382 'token' : window.parent.token,
383 'db' : window.parent.db,
384 'ajax_request' : true,
385 'sql_query' : sql_query,
388 if(data.success == true) {
389 $(this_field).html('<textarea>'+data.value+'</textarea>')
390 .append('<span class="original_data">'+data_value+'</span>');
391 $(".original_data").hide();
394 PMA_ajaxShowMessage(data.error);
398 else if($(this).is('.relation')) {
403 * @var curr_value String containing the current value of this relational field
405 var curr_value = $(this).find('a').text();
408 * @var post_params Object containing parameters for the POST request
411 'ajax_request' : true,
412 'get_relational_values' : true,
413 'db' : window.parent.db,
414 'table' : window.parent.table,
415 'column' : field_name,
416 'token' : window.parent.token,
417 'curr_value' : curr_value
420 $.post('sql.php', post_params, function(data) {
421 $(this_field).html(data.dropdown)
422 .append('<span class="original_data">'+data_value+'</span>');
423 $(".original_data").hide();
426 else if($(this).is('.enum')) {
430 * @var curr_value String containing the current value of this relational field
432 var curr_value = $(this).text();
435 * @var post_params Object containing parameters for the POST request
438 'ajax_request' : true,
439 'get_enum_values' : true,
440 'db' : window.parent.db,
441 'table' : window.parent.table,
442 'column' : field_name,
443 'token' : window.parent.token,
444 'curr_value' : curr_value
447 $.post('sql.php', post_params, function(data) {
448 $(this_field).html(data.dropdown)
449 .append('<span class="original_data">'+data_value+'</span>');
450 $(".original_data").hide();
453 else if($(this).is('.null')) {
455 $(this_field).html('<textarea></textarea>')
456 .append('<span class="original_data">NULL</span>');
457 $(".original_data").hide();
460 }) // End On click, replace the current field with an input/textarea
463 * After editing, clicking again should post data
466 * @name inline_edit_save
467 * @see PMA_ajaxShowMessage()
468 * @see getFieldName()
470 $(".edit_row_anchor_active").live('click', function(event) {
472 event.preventDefault();
475 * @var this_row Object referring to current row that is being edited
477 var this_row = $(this);
479 // Initialize variables
480 if(disp_mode == 'vertical') {
482 * @var this_row_index Index of the current <td> in the parent <tr>
483 * Current <td> is the inline edit anchor.
485 var this_row_index = $(this).index();
487 * @var input_siblings Object referring to all inline editable events from same row
489 var input_siblings = $(this).parents('tbody').find('tr').find('.data_inline_edit:nth('+this_row_index+')');
491 * @var where_clause String containing the WHERE clause to select this row
493 var where_clause = $(this).parents('tbody').find('tr').find('.where_clause:nth('+this_row_index+')').val();
496 var input_siblings = $(this).parent('tr').find('.data_inline_edit');
497 var where_clause = $(this).parent('tr').find('.where_clause').val();
501 * @var nonunique Boolean, whether this row is unique or not
503 if($(this).is('.nonunique')) {
510 // Collect values of all fields to submit, we don't know which changed
512 * @var params_to_submit Array containing the name/value pairs of all fields
514 var params_to_submit = {};
516 * @var relation_fields Array containing the name/value pairs of relational fields
518 var relation_fields = {};
520 * @var transform_fields Array containing the name/value pairs for transformed fields
522 var transform_fields = {};
524 * @var transformation_fields Boolean, if there are any transformed fields in this row
526 var transformation_fields = false;
528 $(input_siblings).each(function() {
531 * @var this_field Object referring to this field (<td>)
533 var this_field = $(this);
535 * @var field_name String containing the name of this field.
536 * @see getFieldName()
538 var field_name = getFieldName($(this), disp_mode);
541 * @var this_field_params Array temporary storage for the name/value of current field
543 var this_field_params = {};
545 if($(this).is('.transformed')) {
546 transformation_fields = true;
549 if($(this).is(":not(.relation, .enum)")) {
550 this_field_params[field_name] = $(this).find('textarea').val();
551 if($(this).is('.transformed')) {
552 $.extend(transform_fields, this_field_params);
556 this_field_params[field_name] = $(this).find('select').val();
558 if($(this).is('.relation')) {
559 $.extend(relation_fields, this_field_params);
563 $.extend(params_to_submit, this_field_params);
567 * @var sql_query String containing the SQL query to update this row
569 var sql_query = 'UPDATE ' + window.parent.table + ' SET ';
571 $.each(params_to_submit, function(key, value) {
572 if(value.length == 0) {
575 sql_query += ' ' + key + "='" + value + "' , ";
577 //Remove the last ',' appended in the above loop
578 sql_query = sql_query.replace(/,\s$/, '');
579 sql_query += ' WHERE ' + where_clause;
582 * @var rel_fields_list String, url encoded representation of {@link relations_fields}
584 var rel_fields_list = $.param(relation_fields);
587 * @var transform_fields_list String, url encoded representation of {@link transform_fields}
589 var transform_fields_list = $.param(transform_fields);
591 // Make the Ajax post after setting all parameters
593 * @var post_params Object containing parameters for the POST request
595 var post_params = {'ajax_request' : true,
596 'sql_query' : sql_query,
597 'disp_direction' : disp_mode,
598 'token' : window.parent.token,
599 'db' : window.parent.db,
600 'table' : window.parent.table,
601 'clause_is_unique' : nonunique,
602 'where_clause' : where_clause,
603 'rel_fields_list' : rel_fields_list,
604 'do_transformations' : transformation_fields,
605 'transform_fields_list' : transform_fields_list,
609 $.post('tbl_replace.php', post_params, function(data) {
610 if(data.success == true) {
611 PMA_ajaxShowMessage(data.message);
612 $(this_row).removeClass('edit_row_anchor_active').addClass('edit_row_anchor');
614 $(input_siblings).each(function() {
615 // Inline edit post has been successful.
616 if($(this).is(':not(.relation, .enum)')) {
618 * @var new_html String containing value of the data field after edit
620 var new_html = $(this).find('textarea').val();
622 if($(this).is('.transformed')) {
623 var field_name = getFieldName($(this), disp_mode);
624 var this_field = $(this);
626 $.each(data.transformations, function(key, value) {
627 if(key == field_name) {
628 if($(this_field).is('.text_plain, .application_octetstream')) {
633 var new_value = $(this_field).find('textarea').val();
634 new_html = $(value).append(new_value);
642 var new_html = $(this).find('select').val();
643 if($(this).is('.relation')) {
644 var field_name = getFieldName($(this), disp_mode);
645 var this_field = $(this);
647 $.each(data.relations, function(key, value) {
648 if(key == field_name) {
649 var new_value = $(this_field).find('select').val();
650 new_html = $(value).append(new_value);
656 $(this).html(new_html);
660 PMA_ajaxShowMessage(data.error);
663 }) // End After editing, clicking again should post data
664 }, 'top.frame_content') // end $(document).ready()