From 44fcdaf55bfd25a10409f962adf690020e3f90d0 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 21 Jul 2011 18:22:47 +0700 Subject: [PATCH 01/57] Add new feature: grid editing --- js/functions.js | 13 + js/makegrid.js | 604 +++++++++++++++++++++++- libraries/display_tbl.lib.php | 7 + themes/original/css/theme_right.css.php | 38 +- themes/pmahomme/css/theme_right.css.php | 38 +- 5 files changed, 697 insertions(+), 3 deletions(-) diff --git a/js/functions.js b/js/functions.js index bf695367c3..8d841cf524 100644 --- a/js/functions.js +++ b/js/functions.js @@ -2741,3 +2741,16 @@ function PMA_createqTip($elements, content, options) { $elements.qtip($.extend(true, o, options)); } +/** + * Return value of a cell in a table. + */ +function PMA_getCellValue(td) { + if ($(td).is('.null')) { + return ''; + } else if ($(td).is(':not(.truncated, .transformed, .relation, .enum, .set, .null)')) { + return $(td).find('span').html().replace(/
/g, "\n"); + } else { + return $(td).text(); + } +} + diff --git a/js/makegrid.js b/js/makegrid.js index a5bbdb89cf..1997bdf8ee 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -21,6 +21,11 @@ showColVisibHint: false, showAllColText: '', // string, text for "show all" button under column visibility list visibleHeadersCount: 0, // number of visible data headers + isCellEditActive: false, // true if current focus is in edit cell + isEditCellTextEditable: false, // true if current edit cell is editable in the text input box (not textarea) + currentEditCell: null, // reference to that currently being edited + inEditMode: false, // true if grid is in edit mode + cellEditHint: '', // text hint when doing grid edit // functions dragStartRsz: function(e, obj) { // start column resize @@ -34,6 +39,9 @@ }; $('body').css('cursor', 'col-resize'); $('body').noSelect(); + if (g.isInEditMode) { + g.hideEditCell(); + } }, dragStartMove: function(e, obj) { // start column move @@ -65,6 +73,9 @@ this.qtip.hide(); $('body').css('cursor', 'move'); $('body').noSelect(); + if (g.isInEditMode) { + g.hideEditCell(); + } }, dragMove: function(e) { @@ -437,6 +448,534 @@ } } this.afterToggleCol(); + }, + + /** + * Show edit cell, if it can be shown or it is forced. + */ + showEditCell: function(cell, force) { + if (g.isInEditMode && + $(cell).is('.inline_edit') && + !g.colRsz && !g.colMov) + { + if (!g.isCellEditActive || force) { + $cell = $(cell); + // remove all edit area and hide it + $(g.cEdit).find('.edit_area').empty().hide(); + // reposition the cEdit element + $(g.cEdit).css({ + top: $cell.position().top, + left: $cell.position().left, + }) + .show() + .find('input') + .css({ + width: $cell.outerWidth() - 16, + height: $cell.outerHeight() + }); + // fill the cell edit with text from , if it is not null + var value = $cell.is(':not(.null)') ? PMA_getCellValue(cell) : ''; + $(g.cEdit).find('input') + .val(value); + + g.isCellEditActive = false; + g.currentEditCell = cell; + } + } else { + g.hideEditCell(); + } + }, + + /** + * Remove edit cell and the edit area, if it is shown. + * + * @param force Optional, force to hide edit cell without saving edited field. + * @param data Optional, data from the POST AJAX request to save the edited field. + */ + hideEditCell: function(force, data) { + if (g.isCellEditActive && !force) { + // cell is being edited, post the edited data + g.isCellEditActive = false; + g.postEditedCell(); + return; + } + $(g.cEdit).hide(); + $(g.cEdit).find('input[type=text]').blur(); + g.isCellEditActive = false; + + if (data) { + // Cell edit post has been successful. + $this_field = $(g.currentEditCell); + $this_field_span = $this_field.children('span'); + + var is_null = $(g.cEdit).find('input:checkbox').is(':checked'); + if (is_null) { + $this_field_span.html('NULL'); + $this_field.addClass('null'); + } else { + $this_field.removeClass('null'); + if($this_field.is(':not(.relation, .enum, .set)')) { + /** + * @var new_html String containing value of the data field after edit + */ + var new_html = $(g.cEdit).find('textarea').val(); + + if($this_field.is('.transformed')) { + var field_name = getFieldName($this_field); + if (typeof data.transformations != 'undefined') { + $.each(data.transformations, function(key, value) { + if(key == field_name) { + if($this_field.is('.text_plain, .application_octetstream')) { + new_html = value; + return false; + } else { + var new_value = $(g.cEdit).find('textarea').val(); + new_html = $(value).append(new_value); + return false; + } + } + }) + } + } + // replace '\n' with
+ new_html = new_html.replace(/\n/g, '
'); + } else { + var new_html = ''; + var new_value = ''; + $test_element = $(g.cEdit).find('select'); + if ($test_element.length != 0) { + new_value = $test_element.val(); + } + $test_element = $this_field.find('span.curr_value'); + if ($test_element.length != 0) { + new_value = $test_element.text(); + } + + if($this_field.is('.relation')) { + var field_name = getFieldName($this_field); + if (typeof data.relations != 'undefined') { + $.each(data.relations, function(key, value) { + if(key == field_name) { + new_html = $(value); + return false; + } + }) + } + } else if ($this_field.is('.enum')) { + new_html = new_value; + } else if ($this_field.is('.set')) { + if (new_value != null) { + $.each(new_value, function(key, value) { + new_html = new_html + value + ','; + }) + new_html = new_html.substring(0, new_html.length-1); + } + } + } + $this_field_span.html(new_html); + } + // refresh the grid + this.reposRsz(); + this.reposDrop(); + } // end of if "data" is defined, i.e. post successful + }, + + /** + * Show drop-down edit area when edit cell is clicked. + */ + showEditArea: function() { + if (!this.isCellEditActive) { // make sure we don't have focus on other edit cell + g.isCellEditActive = true; + g.isEditCellTextEditable = false; + var $td = $(g.currentEditCell); + var $editArea = $(this.cEdit).find('.edit_area'); + var where_clause = $td.parent('tr').find('.where_clause').val(); + /** + * @var field_name String containing the name of this field. + * @see getFieldName() + */ + var field_name = getFieldName($td); + /** + * @var relation_curr_value String current value of the field (for fields that are foreign keyed). + */ + var relation_curr_value = $td.find('a').text(); + /** + * @var relation_key_or_display_column String relational key if in 'Relational display column' mode, + * relational display column if in 'Relational key' mode (for fields that are foreign keyed). + */ + var relation_key_or_display_column = $td.find('a').attr('title'); + + // empty all edit area, then rebuild it based on $td classes + $editArea.empty(); + + if ($td.is(':not(.not_null)')) { + // append a null checkbox + $editArea.append('
Null :
'); + var $checkbox = $editArea.find('.null_div input'); + // check if current is NULL + if ($td.is('.null')) { + $checkbox.attr('checked', true); + } + + // if the select/editor is changed un-check the 'checkbox_null__'. + if ($td.is('.enum, .set')) { + $editArea.find('select').live('change', function(e) { + $checkbox.attr('checked', false); + }) + } else if ($td.is('.relation')) { + $editArea.find('select').live('change', function(e) { + $checkbox.attr('checked', false); + }) + $editArea.find('.browse_foreign').live('click', function(e) { + $checkbox.attr('checked', false); + }) + } else { + $(g.cEdit).find('input[type=text]').live('change', function(e) { + $checkbox.attr('checked', false); + }) + $editArea.find('textarea').live('keydown', function(e) { + $checkbox.attr('checked', false); + }) + } + + // if 'checkbox_null__' is clicked empty the corresponding select/editor. + $checkbox.click(function(e) { + if ($td.is('.enum')) { + $editArea.find('select').attr('value', ''); + } else if ($td.is('.set')) { + $editArea.find('select').find('option').each(function() { + var $option = $(this); + $option.attr('selected', false); + }) + } else if ($td.is('.relation')) { + // if the dropdown is there to select the foreign value + if ($editArea.find('select').length > 0) { + $editArea.find('select').attr('value', ''); + } + } else { + $editArea.find('textarea').val(''); + } + $(g.cEdit).find('input[type=text]').val(''); + }) + } + + if($td.is('.truncated, .transformed')) { + /** @lends jQuery */ + //handle truncated/transformed values values + $editArea.addClass('edit_area_loading'); + + /** + * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data + */ + var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause); + + // Make the Ajax call and get the data, wrap it and insert it + $.post('sql.php', { + 'token' : window.parent.token, + 'db' : window.parent.db, + 'ajax_request' : true, + 'sql_query' : sql_query, + 'inline_edit' : true + }, function(data) { + $editArea.removeClass('edit_area_loading'); + if(data.success == true) { + $(g.cEdit).find('input[type=text]').val(data.value); + $editArea.append(''); + $editArea.find('textarea').live('keyup', function(e) { + $(g.cEdit).find('input[type=text]').val($(this).val()); + }); + $(g.cEdit).find('input[type=text]').live('keyup', function(e) { + $editArea.find('textarea').val($(this).val()); + }); + $editArea.append('
' + g.cellEditHint + '
'); + } + else { + PMA_ajaxShowMessage(data.error); + } + }) // end $.post() + g.isEditCellTextEditable = true; + } + else if($td.is('.relation')) { + /** @lends jQuery */ + //handle relations + $editArea.addClass('edit_area_loading'); + + /** + * @var post_params Object containing parameters for the POST request + */ + var post_params = { + 'ajax_request' : true, + 'get_relational_values' : true, + 'db' : window.parent.db, + 'table' : window.parent.table, + 'column' : field_name, + 'token' : window.parent.token, + 'curr_value' : relation_curr_value, + 'relation_key_or_display_column' : relation_key_or_display_column + } + + $.post('sql.php', post_params, function(data) { + $editArea.removeClass('edit_area_loading'); + $editArea.append(data.dropdown); + $editArea.append('
' + g.cellEditHint + '
'); + }) // end $.post() + + $editArea.find('select').live('change', function(e) { + $(g.cEdit).find('input[type=text]').val($(this).val()); + }) + } + else if($td.is('.enum')) { + /** @lends jQuery */ + //handle enum fields + $editArea.addClass('edit_area_loading'); + + /** + * @var post_params Object containing parameters for the POST request + */ + var post_params = { + 'ajax_request' : true, + 'get_enum_values' : true, + 'db' : window.parent.db, + 'table' : window.parent.table, + 'column' : field_name, + 'token' : window.parent.token, + 'curr_value' : curr_value + } + $.post('sql.php', post_params, function(data) { + $editArea.removeClass('edit_area_loading'); + $editArea.append(data.dropdown); + $editArea.append('
' + g.cellEditHint + '
'); + }) // end $.post() + + $editArea.find('select').live('change', function(e) { + $(g.cEdit).find('input[type=text]').val($(this).val()); + }) + } + else if($td.is('.set')) { + /** @lends jQuery */ + //handle set fields + $editArea.addClass('edit_area_loading'); + + /** + * @var post_params Object containing parameters for the POST request + */ + var post_params = { + 'ajax_request' : true, + 'get_set_values' : true, + 'db' : window.parent.db, + 'table' : window.parent.table, + 'column' : field_name, + 'token' : window.parent.token, + 'curr_value' : curr_value + } + + $.post('sql.php', post_params, function(data) { + $editArea.removeClass('edit_area_loading'); + $editArea.append(data.select); + $editArea.append('
' + g.cellEditHint + '
'); + }) // end $.post() + + $editArea.find('select').live('change', function(e) { + $(g.cEdit).find('input[type=text]').val($(this).val()); + }) + } else { + $editArea.append(''); + $editArea.find('textarea').live('keyup', function(e) { + $(g.cEdit).find('input[type=text]').val($(this).val()); + }); + $(g.cEdit).find('input[type=text]').live('keyup', function(e) { + $editArea.find('textarea').val($(this).val()); + }); + $editArea.append('
' + g.cellEditHint + '
'); + g.isEditCellTextEditable = true; + } + + $editArea.show(); + } + }, + + /** + * Post the content of edited cell. + */ + postEditedCell: function() { + + event.preventDefault(); + + /** + * @var $this_field Object referring to the td that is being edited + */ + var $this_field = $(g.currentEditCell); + var $test_element = ''; // to test the presence of a element + + // Initialize variables + var where_clause = $this_field.parent('tr').find('.where_clause').val(); + + /** + * @var nonunique Boolean, whether this row is unique or not + */ + var nonunique = $this_field.is('.nonunique') ? 0 : 1; + /** + * @var relation_fields Array containing the name/value pairs of relational fields + */ + var relation_fields = {}; + /** + * @var relational_display string 'K' if relational key, 'D' if relational display column + */ + var relational_display = $("#relational_display_K").attr('checked') ? 'K' : 'D'; + /** + * @var transform_fields Array containing the name/value pairs for transformed fields + */ + var transform_fields = {}; + /** + * @var transformation_fields Boolean, if there are any transformed fields in this row + */ + var transformation_fields = false; + + /** + * @var sql_query String containing the SQL query to update this row + */ + var sql_query = 'UPDATE `' + window.parent.table + '` SET '; + + var need_to_post = false; + + var new_clause = ''; + + /** + * @var field_name String containing the name of this field. + * @see getFieldName() + */ + var field_name = getFieldName($this_field); + + /** + * @var this_field_params Array temporary storage for the name/value of current field + */ + var this_field_params = {}; + + if($this_field.is('.transformed')) { + transformation_fields = true; + } + /** + * @var is_null String capturing whether 'checkbox_null__' is checked. + */ + var is_null = $(g.cEdit).find('input:checkbox').is(':checked'); + var value; + var addQuotes = true; + + if (is_null) { + sql_query += ' `' + field_name + "`=NULL , "; + need_to_post = true; + } else { + if($this_field.is(":not(.relation, .enum, .set, .bit)")) { + this_field_params[field_name] = $(g.cEdit).find('textarea').val(); + if($this_field.is('.transformed')) { + $.extend(transform_fields, this_field_params); + } + } else if ($this_field.is('.bit')) { + this_field_params[field_name] = '0b' + $(g.cEdit).find('textarea').val(); + addQuotes = false; + } else if ($this_field.is('.set')) { + $test_element = $(g.cEdit).find('select'); + this_field_params[field_name] = $test_element.map(function(){ + return $(this).val(); + }).get().join(","); + } else { + // results from a drop-down + $test_element = $(g.cEdit).find('select'); + if ($test_element.length != 0) { + this_field_params[field_name] = $test_element.val(); + } + + // results from Browse foreign value + $test_element = $(g.cEdit).find('textarea'); + if ($test_element.length != 0) { + this_field_params[field_name] = $test_element.val(); + } + + if($this_field.is('.relation')) { + $.extend(relation_fields, this_field_params); + } + } + if (where_clause.indexOf(field_name) > -1) { + new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND '; + } + if (this_field_params[field_name] != PMA_getCellValue(g.currentEditCell)) { + if (addQuotes == true) { + sql_query += ' `' + field_name + "`='" + this_field_params[field_name].replace(/'/g, "''") + "', "; + } else { + sql_query += ' `' + field_name + "`=" + this_field_params[field_name].replace(/'/g, "''") + ", "; + } + need_to_post = true; + } + } + + /* + * update the where_clause, remove the last appended ' AND ' + * */ + + //Remove the last ',' appended in the above loop + sql_query = sql_query.replace(/,\s$/, ''); + //Fix non-escaped backslashes + sql_query = sql_query.replace(/\\/g, '\\\\'); + new_clause = new_clause.substring(0, new_clause.length-5); + new_clause = PMA_urlencode(new_clause); + sql_query += ' WHERE ' + PMA_urldecode(where_clause); + // Avoid updating more than one row in case there is no primary key + // (happened only for duplicate rows) + sql_query += ' LIMIT 1'; + /** + * @var rel_fields_list String, url encoded representation of {@link relations_fields} + */ + var rel_fields_list = $.param(relation_fields); + + /** + * @var transform_fields_list String, url encoded representation of {@link transform_fields} + */ + var transform_fields_list = $.param(transform_fields); + + if (need_to_post) { + // Make the Ajax post after setting all parameters + /** + * @var post_params Object containing parameters for the POST request + */ + var post_params = {'ajax_request' : true, + 'sql_query' : sql_query, + 'token' : window.parent.token, + 'db' : window.parent.db, + 'table' : window.parent.table, + 'clause_is_unique' : nonunique, + 'where_clause' : where_clause, + 'rel_fields_list' : rel_fields_list, + 'do_transformations' : transformation_fields, + 'transform_fields_list' : transform_fields_list, + 'relational_display' : relational_display, + 'goto' : 'sql.php', + 'submit_type' : 'save' + }; + + $.post('tbl_replace.php', post_params, function(data) { + if(data.success == true) { + PMA_ajaxShowMessage(data.message); + if (new_clause != '') { + $this_field.parent('tr').find('.where_clause').attr('value', new_clause); + } + // remove possible previous feedback message + $('#result_query').remove(); + if (typeof data.sql_query != 'undefined') { + // display feedback + $('#sqlqueryresults').prepend(data.sql_query); + } + //PMA_unInlineEditRow($del_hide, $chg_submit, $this_field, $input_siblings, data); + g.hideEditCell(true, data); + } else { + PMA_ajaxShowMessage(data.error); + }; + }) // end $.post() + } else { + // no posting was done but still need to display the row + // in its previous format + //PMA_unInlineEditRow($del_hide, $chg_submit, $this_field, $input_siblings, ''); + g.hideEditCell(); + } } } @@ -450,6 +989,7 @@ g.cPointer = document.createElement('div'); // column pointer, used when reordering column g.cDrop = document.createElement('div'); // column drop-down arrows g.cList = document.createElement('div'); // column visibility list + g.cEdit = document.createElement('div'); // cell edit // adjust g.cCpy g.cCpy.className = 'cCpy'; @@ -466,6 +1006,11 @@ g.cList.className = 'cList'; $(g.cList).hide(); + // adjust g.cEdit + g.cEdit.className = 'cEdit'; + $(g.cEdit).html('
'); + $(g.cEdit).hide(); + // chain table and grid together t.grid = g; g.t = t; @@ -494,6 +1039,9 @@ g.colVisibHint = $('#col_visib_hint').val(); g.showAllColText = $('#show_all_col_text').val(); + // assign cell editing hint + g.cellEditHint = $('#cell_edit_hint').val(); + // initialize column order $col_order = $('#col_order'); if ($col_order.length > 0) { @@ -596,6 +1144,16 @@ // create qtip for each with draggable class PMA_createqTip($(t).find('th.draggable')); + // enable "Edit table" button + $('.edit_mode').removeClass('hide') + .click(function(e) { + g.isInEditMode = !g.isInEditMode; + $('.edit_mode input').toggleClass('edit_mode_active', g.isInEditMode); + if (!g.isInEditMode) { + g.hideEditCell(); + } + }); + // register events if (g.reorderHint) { // make sure columns is reorderable $(t).find('th.draggable') @@ -662,7 +1220,50 @@ $(t).find('td, th.draggable').mouseenter(function() { g.hideColList(); }); - + // edit cell event + $(t).find('td.data') + .mouseenter(function() { + g.showEditCell(this); + }) + .click(function(e) { + if (g.isCellEditActive) { + g.postEditedCell(); + e.stopPropagation(); + } else { + g.showEditCell(this); + $(g.cEdit).find('input[type=text]').focus(); + e.stopPropagation(); + } + }); + $(g.cEdit).find('input[type=text]').focus(function(e) { + g.showEditArea(); + }); + $(g.cEdit).find('input[type=text], select').live('keydown', function(e) { + if (e.which == 13) { + // post on pressing "Enter" + e.preventDefault(); + g.postEditedCell(); + } + }); + $(g.cEdit).keydown(function(e) { + if (e.which == 27) { + // cancel on pressing "Esc" + g.hideEditCell(true); + } else if (!g.isEditCellTextEditable) { + // prevent text editing + e.preventDefault(); + } + }); + $(g.cEdit).click(function(e) { + // prevent click to be handled by $('html').click below + e.stopPropagation(); + }); + $('html').click(function(e) { + // post edited cell + if (g.isCellEditActive) { + g.postEditedCell(); + } + }); // add table class $(t).addClass('pma_table'); @@ -674,6 +1275,7 @@ $(g.gDiv).append(g.cDrop); $(g.gDiv).append(g.cList); $(g.gDiv).append(g.cCpy); + $(g.gDiv).append(g.cEdit); // some adjustment g.refreshRestoreButton(); diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index a120037ebc..7124207995 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -392,6 +392,13 @@ function PMA_displayTableNavigation($pos_next, $pos_prev, $sql_query, $id_for_di echo ''; } ?> + +
+ + +
+ '; ?> +
diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index 70a3746a58..4f8432a013 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -2225,7 +2225,7 @@ span.mysql-number { font-weight: bold; } -.navigation input[type=submit]:hover { +.navigation input[type=submit]:hover, .navigation input.edit_mode_active { background: #333; color: white; cursor: pointer; @@ -2234,3 +2234,39 @@ span.mysql-number { .navigation select { margin: 0 0.8em; } + +.cEdit { + margin: 0; + padding: 0; + position: absolute; +} + +.cEdit input[type=text] { + background: #FFF url(getImgPath(); ?>b_more.png) no-repeat right; + height: 100%; + margin: 0; + padding: 0 16px 0 0; +} + +.cEdit .edit_area { + background: #FFF; + border: 1px solid #CCC; + min-width: 10em; + padding: 0.3em 0.5em; +} + +.cEdit .edit_area select, .cEdit .edit_area textarea { + width: 97%; +} + +.cEdit .cell_edit_hint { + color: #555; + font-size: 0.8em; + margin: 0.3em 0.2em; +} + +.edit_area_loading { + background: #FFF url(getImgPath(); ?>ajax_clock_small.gif) no-repeat center; + height: 10em; +} + diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index af26481f4d..2afcf57e4e 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -2600,7 +2600,7 @@ span.mysql-number { -moz-border-radius: 0; } -.navigation input[type=submit]:hover { +.navigation input[type=submit]:hover, .navigation input.edit_mode_active { color: white; cursor: pointer; text-shadow: none; @@ -2616,3 +2616,39 @@ span.mysql-number { .navigation select { margin: 0 0.8em; } + +.cEdit { + margin: 0; + padding: 0; + position: absolute; +} + +.cEdit input[type=text] { + background: #FFF url(./themes/pmahomme/img/b_more.png) no-repeat right; + height: 100%; + margin: 0; + padding: 0 16px 0 0; +} + +.cEdit .edit_area { + background: #FFF; + border: 1px solid #CCC; + min-width: 10em; + padding: 0.3em 0.5em; +} + +.cEdit .edit_area select, .cEdit .edit_area textarea { + width: 97%; +} + +.cEdit .cell_edit_hint { + color: #555; + font-size: 0.8em; + margin: 0.3em 0.2em; +} + +.edit_area_loading { + background: #FFF url(./themes/pmahomme/img/ajax_clock_small.gif) no-repeat center; + height: 10em; +} + From 9c06a339828f7374f516bbab6f09749ca53811d8 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 22 Jul 2011 11:15:31 +0800 Subject: [PATCH 02/57] Grid edit: fix bug - error when editing foreign values that must be browsed --- js/makegrid.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index abfb76d7e8..af632d99ae 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -887,9 +887,9 @@ } // results from Browse foreign value - $test_element = $(g.cEdit).find('textarea'); + $test_element = $(g.cEdit).find('span.curr_value'); if ($test_element.length != 0) { - this_field_params[field_name] = $test_element.val(); + this_field_params[field_name] = $test_element.text(); } if($this_field.is('.relation')) { @@ -1227,13 +1227,15 @@ g.showEditCell(this); }) .click(function(e) { - if (g.isCellEditActive) { - g.postEditedCell(); - e.stopPropagation(); - } else { - g.showEditCell(this); - $(g.cEdit).find('input[type=text]').focus(); - e.stopPropagation(); + if (g.isInEditMode) { + if (g.isCellEditActive) { + g.postEditedCell(); + e.stopPropagation(); + } else { + g.showEditCell(this); + $(g.cEdit).find('input[type=text]').focus(); + e.stopPropagation(); + } } }); $(g.cEdit).find('input[type=text]').focus(function(e) { @@ -1255,14 +1257,12 @@ e.preventDefault(); } }); - $(g.cEdit).click(function(e) { - // prevent click to be handled by $('html').click below - e.stopPropagation(); - }); $('html').click(function(e) { - // post edited cell - if (g.isCellEditActive) { - g.postEditedCell(); + // hide edit cell if the click is not from g.cEdit + if ($(e.target).parents().index(g.cEdit) == -1) { + if (g.isCellEditActive) { + g.hideEditCell(); + } } }); // add table class From 7d729361bb407434b0c4ede473a594766d2f6c6e Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 22 Jul 2011 11:55:25 +0800 Subject: [PATCH 03/57] Grid edit: add loading icon when loading and posting data --- js/makegrid.js | 4 ++++ themes/original/css/theme_right.css.php | 8 +++++++- themes/pmahomme/css/theme_right.css.php | 7 ++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index af632d99ae..5f6cc532b4 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -952,8 +952,12 @@ 'goto' : 'sql.php', 'submit_type' : 'save' }; + + var $editArea = $(g.cEdit).find('.edit_area'); + $editArea.addClass('edit_area_posting'); $.post('tbl_replace.php', post_params, function(data) { + $editArea.removeClass('edit_area_posting'); if(data.success == true) { PMA_ajaxShowMessage(data.message); if (new_clause != '') { diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index a3f2a17f63..2a64ba84a8 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -2488,8 +2488,14 @@ span.mysql-number { margin: 0.3em 0.2em; } -.edit_area_loading { +.cEdit .edit_area_loading { background: #FFF url(getImgPath(); ?>ajax_clock_small.gif) no-repeat center; height: 10em; } + +.cEdit .edit_area_posting { + background: #FFF url(getImgPath(); ?>ajax_clock_small.gif) no-repeat center top; + padding-top: 1.5em; +} + diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index 2d030c0080..8988d10da5 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -2899,8 +2899,13 @@ span.mysql-number { margin: 0.3em 0.2em; } -.edit_area_loading { +.cEdit .edit_area_loading { background: #FFF url(./themes/pmahomme/img/ajax_clock_small.gif) no-repeat center; height: 10em; } +.cEdit .edit_area_posting { + background: #FFF url(./themes/pmahomme/img/ajax_clock_small.gif) no-repeat center top; + padding-top: 1.5em; +} + From 2fd43bafb9f1c04d6b226ea713c0eba0c0d75e61 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 22 Jul 2011 12:00:53 +0800 Subject: [PATCH 04/57] Grid edit: hide edit field when we click outside edit cell --- js/makegrid.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 5f6cc532b4..06a83f7734 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1264,9 +1264,7 @@ $('html').click(function(e) { // hide edit cell if the click is not from g.cEdit if ($(e.target).parents().index(g.cEdit) == -1) { - if (g.isCellEditActive) { - g.hideEditCell(); - } + g.hideEditCell(); } }); // add table class From 756ae599e92cdd1aa0a319c189663fbadc709753 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 22 Jul 2011 12:04:47 +0800 Subject: [PATCH 05/57] Grid edit: press escape key anywhere to cancel editing --- js/makegrid.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 06a83f7734..dadd678aae 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1253,10 +1253,7 @@ } }); $(g.cEdit).keydown(function(e) { - if (e.which == 27) { - // cancel on pressing "Esc" - g.hideEditCell(true); - } else if (!g.isEditCellTextEditable) { + if (!g.isEditCellTextEditable) { // prevent text editing e.preventDefault(); } @@ -1267,6 +1264,12 @@ g.hideEditCell(); } }); + $('html').keydown(function(e) { + if (e.which == 27 && g.isCellEditActive) { + // cancel on pressing "Esc" + g.hideEditCell(true); + } + }); // add table class $(t).addClass('pma_table'); From 225075af94512e35572d8ebfe57ee45851801906 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 22 Jul 2011 13:05:17 +0800 Subject: [PATCH 06/57] Grid edit: fix error in javascript, causing grid edit error in IE --- js/makegrid.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index dadd678aae..fcc750998e 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -799,9 +799,6 @@ * Post the content of edited cell. */ postEditedCell: function() { - - event.preventDefault(); - /** * @var $this_field Object referring to the td that is being edited */ From 647335cc69297dd06c886b891351bc708f9d21b0 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 22 Jul 2011 13:27:25 +0800 Subject: [PATCH 07/57] Inline edit: fix bug - inline edit doesn't take 'server' variable into account --- js/sql.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/sql.js b/js/sql.js index fb24f5da66..aa389fe23d 100644 --- a/js/sql.js +++ b/js/sql.js @@ -621,6 +621,7 @@ $(document).ready(function() { // Make the Ajax call and get the data, wrap it and insert it $.post('sql.php', { 'token' : window.parent.token, + 'server' : window.parent.server, 'db' : window.parent.db, 'ajax_request' : true, 'sql_query' : sql_query, @@ -646,6 +647,7 @@ $(document).ready(function() { var post_params = { 'ajax_request' : true, 'get_relational_values' : true, + 'server' : window.parent.server, 'db' : window.parent.db, 'table' : window.parent.table, 'column' : field_name, @@ -670,6 +672,7 @@ $(document).ready(function() { var post_params = { 'ajax_request' : true, 'get_enum_values' : true, + 'server' : window.parent.server, 'db' : window.parent.db, 'table' : window.parent.table, 'column' : field_name, @@ -692,6 +695,7 @@ $(document).ready(function() { var post_params = { 'ajax_request' : true, 'get_set_values' : true, + 'server' : window.parent.server, 'db' : window.parent.db, 'table' : window.parent.table, 'column' : field_name, @@ -893,6 +897,7 @@ $(document).ready(function() { var post_params = {'ajax_request' : true, 'sql_query' : sql_query, 'token' : window.parent.token, + 'server' : window.parent.server, 'db' : window.parent.db, 'table' : window.parent.table, 'clause_is_unique' : nonunique, From 8570824bebeefc6de1fc14211d2e88e25609cbdc Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 22 Jul 2011 13:25:11 +0800 Subject: [PATCH 08/57] Grid edit: fix bug - grid edit doesn't take 'server' variable into account --- js/makegrid.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/js/makegrid.js b/js/makegrid.js index fcc750998e..7af6ea465c 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -673,6 +673,7 @@ // Make the Ajax call and get the data, wrap it and insert it $.post('sql.php', { 'token' : window.parent.token, + 'server' : window.parent.server, 'db' : window.parent.db, 'ajax_request' : true, 'sql_query' : sql_query, @@ -707,6 +708,7 @@ var post_params = { 'ajax_request' : true, 'get_relational_values' : true, + 'server' : window.parent.server, 'db' : window.parent.db, 'table' : window.parent.table, 'column' : field_name, @@ -736,6 +738,7 @@ var post_params = { 'ajax_request' : true, 'get_enum_values' : true, + 'server' : window.parent.server, 'db' : window.parent.db, 'table' : window.parent.table, 'column' : field_name, @@ -763,6 +766,7 @@ var post_params = { 'ajax_request' : true, 'get_set_values' : true, + 'server' : window.parent.server, 'db' : window.parent.db, 'table' : window.parent.table, 'column' : field_name, @@ -938,6 +942,7 @@ var post_params = {'ajax_request' : true, 'sql_query' : sql_query, 'token' : window.parent.token, + 'server' : window.parent.server, 'db' : window.parent.db, 'table' : window.parent.table, 'clause_is_unique' : nonunique, From c0613bd7e99fb0c58aad5e533df6f5994aa550df Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 25 Jul 2011 12:29:05 +0800 Subject: [PATCH 09/57] Grid edit: remove 'edit mode' --- js/makegrid.js | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 7af6ea465c..a385681250 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -39,7 +39,7 @@ }; $('body').css('cursor', 'col-resize'); $('body').noSelect(); - if (g.isInEditMode) { + if (g.isCellEditActive) { g.hideEditCell(); } }, @@ -73,7 +73,7 @@ this.qtip.hide(); $('body').css('cursor', 'move'); $('body').noSelect(); - if (g.isInEditMode) { + if (g.isCellEditActive) { g.hideEditCell(); } }, @@ -455,8 +455,7 @@ * Show edit cell, if it can be shown or it is forced. */ showEditCell: function(cell, force) { - if (g.isInEditMode && - $(cell).is('.inline_edit') && + if ($(cell).is('.inline_edit') && !g.colRsz && !g.colMov) { if (!g.isCellEditActive || force) { @@ -1151,16 +1150,6 @@ // create qtip for each with draggable class PMA_createqTip($(t).find('th.draggable')); - // enable "Edit table" button - $('.edit_mode').removeClass('hide') - .click(function(e) { - g.isInEditMode = !g.isInEditMode; - $('.edit_mode input').toggleClass('edit_mode_active', g.isInEditMode); - if (!g.isInEditMode) { - g.hideEditCell(); - } - }); - // register events if (g.reorderHint) { // make sure columns is reorderable $(t).find('th.draggable') @@ -1229,19 +1218,14 @@ }); // edit cell event $(t).find('td.data') - .mouseenter(function() { - g.showEditCell(this); - }) .click(function(e) { - if (g.isInEditMode) { - if (g.isCellEditActive) { - g.postEditedCell(); - e.stopPropagation(); - } else { - g.showEditCell(this); - $(g.cEdit).find('input[type=text]').focus(); - e.stopPropagation(); - } + if (g.isCellEditActive) { + g.postEditedCell(); + e.stopPropagation(); + } else { + g.showEditCell(this); + $(g.cEdit).find('input[type=text]').focus(); + e.stopPropagation(); } }); $(g.cEdit).find('input[type=text]').focus(function(e) { From 59cbf2a3f1deab9a30e5304ec929ea2a4efdad4b Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 25 Jul 2011 14:38:57 +0800 Subject: [PATCH 10/57] Grid edit: handle clicking on a link --- js/makegrid.js | 16 +++++++++++++++- themes/original/css/theme_right.css.php | 8 +++++++- themes/pmahomme/css/theme_right.css.php | 8 +++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index a385681250..ad73ba416c 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -25,7 +25,8 @@ isEditCellTextEditable: false, // true if current edit cell is editable in the text input box (not textarea) currentEditCell: null, // reference to that currently being edited inEditMode: false, // true if grid is in edit mode - cellEditHint: '', // text hint when doing grid edit + cellEditHint: '', // hint shown when doing grid edit + gotoLinkText: 'Go to link', // "Go to link" text // functions dragStartRsz: function(e, obj) { // start column resize @@ -608,6 +609,15 @@ // empty all edit area, then rebuild it based on $td classes $editArea.empty(); + // add goto link, if this cell contains a link + if ($td.find('a').length > 0) { + var gotoLink = document.createElement('div'); + gotoLink.className = 'goto_link'; + $(gotoLink).append(g.gotoLinkText + ': ') + .append($td.find('a').clone()); + $editArea.append(gotoLink); + } + if ($td.is(':not(.not_null)')) { // append a null checkbox $editArea.append('
Null :
'); @@ -1227,6 +1237,10 @@ $(g.cEdit).find('input[type=text]').focus(); e.stopPropagation(); } + // prevent default action when clicking on "link" in a table + if ($(e.target).is('a')) { + e.preventDefault(); + } }); $(g.cEdit).find('input[type=text]').focus(function(e) { g.showEditArea(); diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index 2a64ba84a8..b881bd421c 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -2473,7 +2473,7 @@ span.mysql-number { .cEdit .edit_area { background: #FFF; - border: 1px solid #CCC; + border: 1px solid #999; min-width: 10em; padding: 0.3em 0.5em; } @@ -2499,3 +2499,9 @@ span.mysql-number { padding-top: 1.5em; } +.cEdit .goto_link { + background: #EEE; + color: #555; + padding: 0.2em 0.3em; +} + diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index 8988d10da5..061090a01c 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -2884,7 +2884,7 @@ span.mysql-number { .cEdit .edit_area { background: #FFF; - border: 1px solid #CCC; + border: 1px solid #999; min-width: 10em; padding: 0.3em 0.5em; } @@ -2909,3 +2909,9 @@ span.mysql-number { padding-top: 1.5em; } +.cEdit .goto_link { + background: #EEE; + color: #555; + padding: 0.2em 0.3em; +} + From 37027fdce3afebc6bc4a2f21f76c04acc33f7712 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 25 Jul 2011 14:51:56 +0800 Subject: [PATCH 11/57] Grid edit: fix for transformed relational field --- js/makegrid.js | 76 +++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index ad73ba416c..3279070465 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -669,44 +669,7 @@ }) } - if($td.is('.truncated, .transformed')) { - /** @lends jQuery */ - //handle truncated/transformed values values - $editArea.addClass('edit_area_loading'); - - /** - * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data - */ - var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause); - - // Make the Ajax call and get the data, wrap it and insert it - $.post('sql.php', { - 'token' : window.parent.token, - 'server' : window.parent.server, - 'db' : window.parent.db, - 'ajax_request' : true, - 'sql_query' : sql_query, - 'inline_edit' : true - }, function(data) { - $editArea.removeClass('edit_area_loading'); - if(data.success == true) { - $(g.cEdit).find('input[type=text]').val(data.value); - $editArea.append(''); - $editArea.find('textarea').live('keyup', function(e) { - $(g.cEdit).find('input[type=text]').val($(this).val()); - }); - $(g.cEdit).find('input[type=text]').live('keyup', function(e) { - $editArea.find('textarea').val($(this).val()); - }); - $editArea.append('
' + g.cellEditHint + '
'); - } - else { - PMA_ajaxShowMessage(data.error); - } - }) // end $.post() - g.isEditCellTextEditable = true; - } - else if($td.is('.relation')) { + if($td.is('.relation')) { /** @lends jQuery */ //handle relations $editArea.addClass('edit_area_loading'); @@ -792,6 +755,43 @@ $editArea.find('select').live('change', function(e) { $(g.cEdit).find('input[type=text]').val($(this).val()); }) + } + else if($td.is('.truncated, .transformed')) { + /** @lends jQuery */ + //handle truncated/transformed values values + $editArea.addClass('edit_area_loading'); + + /** + * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data + */ + var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause); + + // Make the Ajax call and get the data, wrap it and insert it + $.post('sql.php', { + 'token' : window.parent.token, + 'server' : window.parent.server, + 'db' : window.parent.db, + 'ajax_request' : true, + 'sql_query' : sql_query, + 'inline_edit' : true + }, function(data) { + $editArea.removeClass('edit_area_loading'); + if(data.success == true) { + $(g.cEdit).find('input[type=text]').val(data.value); + $editArea.append(''); + $editArea.find('textarea').live('keyup', function(e) { + $(g.cEdit).find('input[type=text]').val($(this).val()); + }); + $(g.cEdit).find('input[type=text]').live('keyup', function(e) { + $editArea.find('textarea').val($(this).val()); + }); + $editArea.append('
' + g.cellEditHint + '
'); + } + else { + PMA_ajaxShowMessage(data.error); + } + }) // end $.post() + g.isEditCellTextEditable = true; } else { $editArea.append(''); $editArea.find('textarea').live('keyup', function(e) { From 4bfa0b7e5b32a5d3a31d9162748f9bd1cc076521 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 25 Jul 2011 14:52:57 +0800 Subject: [PATCH 12/57] Grid edit: remove drop down arrow in text input box --- js/makegrid.js | 2 +- themes/original/css/theme_right.css.php | 4 ++-- themes/pmahomme/css/theme_right.css.php | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 3279070465..c2c994585b 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -471,7 +471,7 @@ .show() .find('input') .css({ - width: $cell.outerWidth() - 16, + width: $cell.outerWidth(), height: $cell.outerHeight() }); // fill the cell edit with text from , if it is not null diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index b881bd421c..bf3b2b8429 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -2465,10 +2465,10 @@ span.mysql-number { } .cEdit input[type=text] { - background: #FFF url(getImgPath(); ?>b_more.png) no-repeat right; + background: #FFF; height: 100%; margin: 0; - padding: 0 16px 0 0; + padding: 0; } .cEdit .edit_area { diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index 061090a01c..5454f53c30 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -2876,10 +2876,10 @@ span.mysql-number { } .cEdit input[type=text] { - background: #FFF url(./themes/pmahomme/img/b_more.png) no-repeat right; + background: #FFF; height: 100%; margin: 0; - padding: 0 16px 0 0; + padding: 0; } .cEdit .edit_area { From b25ce5afa9891c0b28996b61c068477e9c9d2d3e Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 25 Jul 2011 16:47:59 +0800 Subject: [PATCH 13/57] Grid edit: fix bug - support for SET and ENUM data type --- js/makegrid.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/makegrid.js b/js/makegrid.js index c2c994585b..be08354237 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -605,6 +605,10 @@ * relational display column if in 'Relational key' mode (for fields that are foreign keyed). */ var relation_key_or_display_column = $td.find('a').attr('title'); + /** + * @var curr_value String current value of the field (for fields that are of type enum or set). + */ + var curr_value = $td.find('span').text(); // empty all edit area, then rebuild it based on $td classes $editArea.empty(); From 5faaa14bd72c0a4f4db1080e3de768cccff72b6a Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 25 Jul 2011 16:58:25 +0800 Subject: [PATCH 14/57] Grid edit: fix bug - differentiating NULL and empty string --- js/makegrid.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index be08354237..f5bb9012fa 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -27,6 +27,7 @@ inEditMode: false, // true if grid is in edit mode cellEditHint: '', // hint shown when doing grid edit gotoLinkText: 'Go to link', // "Go to link" text + wasEditedCellNull: false, // true if last value of the edited cell was NULL // functions dragStartRsz: function(e, obj) { // start column resize @@ -622,6 +623,7 @@ $editArea.append(gotoLink); } + g.wasEditedCellNull = false; if ($td.is(':not(.not_null)')) { // append a null checkbox $editArea.append('
Null :
'); @@ -629,6 +631,7 @@ // check if current is NULL if ($td.is('.null')) { $checkbox.attr('checked', true); + g.wasEditedCellNull = true; } // if the select/editor is changed un-check the 'checkbox_null__'. @@ -877,8 +880,10 @@ var addQuotes = true; if (is_null) { - sql_query += ' `' + field_name + "`=NULL , "; - need_to_post = true; + if (!g.wasEditedCellNull) { + sql_query += ' `' + field_name + "`=NULL , "; + need_to_post = true; + } } else { if($this_field.is(":not(.relation, .enum, .set, .bit)")) { this_field_params[field_name] = $(g.cEdit).find('textarea').val(); @@ -913,7 +918,8 @@ if (where_clause.indexOf(field_name) > -1) { new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND '; } - if (this_field_params[field_name] != PMA_getCellValue(g.currentEditCell)) { + if (g.wasEditedCellNull || this_field_params[field_name] != PMA_getCellValue(g.currentEditCell)) + { if (addQuotes == true) { sql_query += ' `' + field_name + "`='" + this_field_params[field_name].replace(/'/g, "''") + "', "; } else { From 4c30640024e9ff159a8e24eb2ef5cd14811d3be9 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 25 Jul 2011 18:09:11 +0800 Subject: [PATCH 15/57] Grid edit: add truncated support for TEXT data type --- js/functions.js | 4 ++-- js/makegrid.js | 10 +++++++++- libraries/display_tbl.lib.php | 12 ++++++++---- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/js/functions.js b/js/functions.js index 0401f5d195..9fe93d15c1 100644 --- a/js/functions.js +++ b/js/functions.js @@ -2953,8 +2953,8 @@ function PMA_createqTip($elements, content, options) { function PMA_getCellValue(td) { if ($(td).is('.null')) { return ''; - } else if ($(td).is(':not(.truncated, .transformed, .relation, .enum, .set, .null)')) { - return $(td).find('span').html().replace(/
/g, "\n"); + } else if ($(td).is(':not(.transformed, .relation, .enum, .set, .null)')) { + return unescape($(td).find('span').html()).replace(/
/g, "\n"); } else { return $(td).text(); } diff --git a/js/makegrid.js b/js/makegrid.js index f5bb9012fa..5c0af4897c 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -28,6 +28,7 @@ cellEditHint: '', // hint shown when doing grid edit gotoLinkText: 'Go to link', // "Go to link" text wasEditedCellNull: false, // true if last value of the edited cell was NULL + maxTruncatedLen: 0, // number of characters that can be displayed in a cell // functions dragStartRsz: function(e, obj) { // start column resize @@ -482,6 +483,7 @@ g.isCellEditActive = false; g.currentEditCell = cell; + $(g.cEdit).find('input[type=text]').focus(); } } else { g.hideEditCell(); @@ -538,6 +540,10 @@ } }) } + } else if ($this_field.is('.truncated')) { + if (new_html.length > g.maxTruncatedLen) { + new_html = new_html.substring(0, g.maxTruncatedLen) + '...'; + } } // replace '\n' with
new_html = new_html.replace(/\n/g, '
'); @@ -784,6 +790,9 @@ }, function(data) { $editArea.removeClass('edit_area_loading'); if(data.success == true) { + // get the truncated data length + g.maxTruncatedLen = PMA_getCellValue(g.currentEditCell).length - 3; + $(g.cEdit).find('input[type=text]').val(data.value); $editArea.append(''); $editArea.find('textarea').live('keyup', function(e) { @@ -1244,7 +1253,6 @@ e.stopPropagation(); } else { g.showEditCell(this); - $(g.cEdit).find('input[type=text]').focus(); e.stopPropagation(); } // prevent default action when clicking on "link" in a table diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index 3f402ed0a6..3ed305b2cb 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -1480,10 +1480,10 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { // TEXT fields type so we have to ensure it's really a BLOB $field_flags = PMA_DBI_field_flags($dt_result, $i); - // remove 'inline_edit' from $class as we can't edit binary data. - $class = str_replace('inline_edit', '', $class); - if (stristr($field_flags, 'BINARY')) { + // remove 'inline_edit' from $class as we can't edit binary data. + $class = str_replace('inline_edit', '', $class); + if (! isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = PMA_buildNullDisplay($class, $condition_field); } else { @@ -1512,7 +1512,11 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { // characters for tabulations and / $row[$i] = ($default_function != $transform_function ? $transform_function($row[$i], $transform_options, $meta) : $default_function($row[$i], array(), $meta)); - $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay($class, $condition_field, $row[$i]); + if ($is_field_truncated) { + $class .= ' truncated'; + } + + $vertical_display['data'][$row_no][$i] = PMA_buildValueDisplay($class, $condition_field, $row[$i]); } else { $vertical_display['data'][$row_no][$i] = PMA_buildEmptyDisplay($class, $condition_field, $meta); } From 03a024f4e32c7d89d646b2fda6b0e839a339a04e Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Tue, 26 Jul 2011 09:10:50 +0800 Subject: [PATCH 16/57] Grid edit: disable edited element when posting to server --- js/makegrid.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/js/makegrid.js b/js/makegrid.js index 5c0af4897c..daea73960e 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -484,6 +484,7 @@ g.isCellEditActive = false; g.currentEditCell = cell; $(g.cEdit).find('input[type=text]').focus(); + $(g.cEdit).find('*').attr('disabled', false); } } else { g.hideEditCell(); @@ -985,6 +986,7 @@ var $editArea = $(g.cEdit).find('.edit_area'); $editArea.addClass('edit_area_posting'); + $(g.cEdit).find('*').attr('disabled', true); $.post('tbl_replace.php', post_params, function(data) { $editArea.removeClass('edit_area_posting'); From cb090c7e21d1c30f46b9682ef6e10caceced4274 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Tue, 26 Jul 2011 18:30:40 +0800 Subject: [PATCH 17/57] Grid edit: add configuration to save edited cell(s) at once --- Documentation.html | 5 + js/makegrid.js | 411 ++++++++++++-------- libraries/config.default.php | 5 + libraries/config/messages.inc.php | 1 + libraries/config/setup.forms.php | 1 + libraries/config/user_preferences.forms.php | 1 + libraries/display_tbl.lib.php | 6 +- 7 files changed, 255 insertions(+), 175 deletions(-) diff --git a/Documentation.html b/Documentation.html index 6a8d5dcd16..8129027e01 100644 --- a/Documentation.html +++ b/Documentation.html @@ -2143,6 +2143,11 @@ setfacl -d -m "g:www-data:rwx" tmp identify what they mean. +
$cfg['SaveCellsAtOnce'] boolean
+
+ Defines whether or not to save all edited cells at once in browse-mode. +
+
$cfg['ShowDisplayDirection'] boolean
Defines whether or not type display direction option is shown diff --git a/js/makegrid.js b/js/makegrid.js index daea73960e..9d9aab1986 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -29,6 +29,9 @@ gotoLinkText: 'Go to link', // "Go to link" text wasEditedCellNull: false, // true if last value of the edited cell was NULL maxTruncatedLen: 0, // number of characters that can be displayed in a cell + saveCellsAtOnce: false, // $cfg[saveCellsAtOnce] + isCellEdited: false, // true if at least one cell has been edited + saveCellWarning: '', // string, warning text when user want to leave a page with unsaved edited data // functions dragStartRsz: function(e, obj) { // start column resize @@ -495,13 +498,16 @@ * Remove edit cell and the edit area, if it is shown. * * @param force Optional, force to hide edit cell without saving edited field. - * @param data Optional, data from the POST AJAX request to save the edited field. + * @param data Optional, data from the POST AJAX request to save the edited field + * or just specify "true", if we want to replace the edited field with the new value. + * @param field Optional, the edited . If not specified, the function will + * use currently edited from g.currentEditCell. */ - hideEditCell: function(force, data) { + hideEditCell: function(force, data, field) { if (g.isCellEditActive && !force) { // cell is being edited, post the edited data g.isCellEditActive = false; - g.postEditedCell(); + g.saveOrPostEditedCell(); return; } $(g.cEdit).hide(); @@ -509,22 +515,21 @@ g.isCellEditActive = false; if (data) { - // Cell edit post has been successful. - $this_field = $(g.currentEditCell); + $this_field = field == undefined ? $(g.currentEditCell) : $(field); $this_field_span = $this_field.children('span'); - var is_null = $(g.cEdit).find('input:checkbox').is(':checked'); + var is_null = $this_field.data('value') == null; if (is_null) { $this_field_span.html('NULL'); $this_field.addClass('null'); } else { $this_field.removeClass('null'); - if($this_field.is(':not(.relation, .enum, .set)')) { - /** - * @var new_html String containing value of the data field after edit - */ - var new_html = $(g.cEdit).find('textarea').val(); + /** + * @var new_html String containing value of the data field after edit + */ + var new_html = $this_field.data('value'); + if($this_field.is(':not(.relation, .enum, .set)')) { if($this_field.is('.transformed')) { var field_name = getFieldName($this_field); if (typeof data.transformations != 'undefined') { @@ -534,7 +539,7 @@ new_html = value; return false; } else { - var new_value = $(g.cEdit).find('textarea').val(); + var new_value = $this_field.data('value'); new_html = $(value).append(new_value); return false; } @@ -549,17 +554,6 @@ // replace '\n' with
new_html = new_html.replace(/\n/g, '
'); } else { - var new_html = ''; - var new_value = ''; - $test_element = $(g.cEdit).find('select'); - if ($test_element.length != 0) { - new_value = $test_element.val(); - } - $test_element = $this_field.find('span.curr_value'); - if ($test_element.length != 0) { - new_value = $test_element.text(); - } - if($this_field.is('.relation')) { var field_name = getFieldName($this_field); if (typeof data.relations != 'undefined') { @@ -570,15 +564,6 @@ } }) } - } else if ($this_field.is('.enum')) { - new_html = new_value; - } else if ($this_field.is('.set')) { - if (new_value != null) { - $.each(new_value, function(key, value) { - new_html = new_html + value + ','; - }) - new_html = new_html.substring(0, new_html.length-1); - } } } $this_field_span.html(new_html); @@ -607,7 +592,7 @@ /** * @var relation_curr_value String current value of the field (for fields that are foreign keyed). */ - var relation_curr_value = $td.find('a').text(); + var relation_curr_value = $td.text(); /** * @var relation_key_or_display_column String relational key if in 'Relational display column' mode, * relational display column if in 'Relational key' mode (for fields that are foreign keyed). @@ -829,141 +814,116 @@ * Post the content of edited cell. */ postEditedCell: function() { - /** - * @var $this_field Object referring to the td that is being edited - */ - var $this_field = $(g.currentEditCell); - var $test_element = ''; // to test the presence of a element + $('.to_be_saved').each(function() { + /** + * @var $this_field Object referring to the td that is being edited + */ + var $this_field = $(this); + + // remove the to_be_saved class + $this_field.removeClass('to_be_saved'); + + var $test_element = ''; // to test the presence of a element - // Initialize variables - var where_clause = $this_field.parent('tr').find('.where_clause').val(); + // Initialize variables + var where_clause = $this_field.parent('tr').find('.where_clause').val(); - /** - * @var nonunique Boolean, whether this row is unique or not - */ - var nonunique = $this_field.is('.nonunique') ? 0 : 1; - /** - * @var relation_fields Array containing the name/value pairs of relational fields - */ - var relation_fields = {}; - /** - * @var relational_display string 'K' if relational key, 'D' if relational display column - */ - var relational_display = $("#relational_display_K").attr('checked') ? 'K' : 'D'; - /** - * @var transform_fields Array containing the name/value pairs for transformed fields - */ - var transform_fields = {}; - /** - * @var transformation_fields Boolean, if there are any transformed fields in this row - */ - var transformation_fields = false; + /** + * @var nonunique Boolean, whether this row is unique or not + */ + var nonunique = $this_field.is('.nonunique') ? 0 : 1; + /** + * @var relation_fields Array containing the name/value pairs of relational fields + */ + var relation_fields = {}; + /** + * @var relational_display string 'K' if relational key, 'D' if relational display column + */ + var relational_display = $("#relational_display_K").attr('checked') ? 'K' : 'D'; + /** + * @var transform_fields Array containing the name/value pairs for transformed fields + */ + var transform_fields = {}; + /** + * @var transformation_fields Boolean, if there are any transformed fields in this row + */ + var transformation_fields = false; - /** - * @var sql_query String containing the SQL query to update this row - */ - var sql_query = 'UPDATE `' + window.parent.table + '` SET '; + /** + * @var sql_query String containing the SQL query to update this row + */ + var sql_query = 'UPDATE `' + window.parent.table + '` SET '; - var need_to_post = false; + var new_clause = ''; - var new_clause = ''; + /** + * @var field_name String containing the name of this field. + * @see getFieldName() + */ + var field_name = getFieldName($this_field); - /** - * @var field_name String containing the name of this field. - * @see getFieldName() - */ - var field_name = getFieldName($this_field); + /** + * @var this_field_params Array temporary storage for the name/value of current field + */ + var this_field_params = {}; - /** - * @var this_field_params Array temporary storage for the name/value of current field - */ - var this_field_params = {}; - - if($this_field.is('.transformed')) { - transformation_fields = true; - } - /** - * @var is_null String capturing whether 'checkbox_null__' is checked. - */ - var is_null = $(g.cEdit).find('input:checkbox').is(':checked'); - var value; - var addQuotes = true; - - if (is_null) { - if (!g.wasEditedCellNull) { - sql_query += ' `' + field_name + "`=NULL , "; - need_to_post = true; + if($this_field.is('.transformed')) { + transformation_fields = true; } - } else { - if($this_field.is(":not(.relation, .enum, .set, .bit)")) { - this_field_params[field_name] = $(g.cEdit).find('textarea').val(); - if($this_field.is('.transformed')) { - $.extend(transform_fields, this_field_params); - } - } else if ($this_field.is('.bit')) { - this_field_params[field_name] = '0b' + $(g.cEdit).find('textarea').val(); - addQuotes = false; - } else if ($this_field.is('.set')) { - $test_element = $(g.cEdit).find('select'); - this_field_params[field_name] = $test_element.map(function(){ - return $(this).val(); - }).get().join(","); + /** + * @var is_null String capturing whether 'checkbox_null__' is checked. + */ + var is_null = $this_field.data('value') == null; + var value; + var addQuotes = true; + + if (is_null) { + sql_query += ' `' + field_name + "`=NULL , "; } else { - // results from a drop-down - $test_element = $(g.cEdit).find('select'); - if ($test_element.length != 0) { - this_field_params[field_name] = $test_element.val(); - } - - // results from Browse foreign value - $test_element = $(g.cEdit).find('span.curr_value'); - if ($test_element.length != 0) { - this_field_params[field_name] = $test_element.text(); - } - - if($this_field.is('.relation')) { + this_field_params[field_name] = $this_field.data('value'); + if($this_field.is(":not(.relation, .enum, .set, .bit)")) { + if($this_field.is('.transformed')) { + $.extend(transform_fields, this_field_params); + } + } else if ($this_field.is('.bit')) { + addQuotes = false; + } else if($this_field.is('.relation')) { $.extend(relation_fields, this_field_params); } - } - if (where_clause.indexOf(field_name) > -1) { - new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND '; - } - if (g.wasEditedCellNull || this_field_params[field_name] != PMA_getCellValue(g.currentEditCell)) - { + if (where_clause.indexOf(field_name) > -1) { + new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND '; + } if (addQuotes == true) { sql_query += ' `' + field_name + "`='" + this_field_params[field_name].replace(/'/g, "''") + "', "; } else { sql_query += ' `' + field_name + "`=" + this_field_params[field_name].replace(/'/g, "''") + ", "; } - need_to_post = true; } - } + + /* + * update the where_clause, remove the last appended ' AND ' + * */ - /* - * update the where_clause, remove the last appended ' AND ' - * */ + //Remove the last ',' appended in the above loop + sql_query = sql_query.replace(/,\s$/, ''); + //Fix non-escaped backslashes + sql_query = sql_query.replace(/\\/g, '\\\\'); + new_clause = new_clause.substring(0, new_clause.length-5); + new_clause = PMA_urlencode(new_clause); + sql_query += ' WHERE ' + PMA_urldecode(where_clause); + // Avoid updating more than one row in case there is no primary key + // (happened only for duplicate rows) + sql_query += ' LIMIT 1'; + /** + * @var rel_fields_list String, url encoded representation of {@link relations_fields} + */ + var rel_fields_list = $.param(relation_fields); - //Remove the last ',' appended in the above loop - sql_query = sql_query.replace(/,\s$/, ''); - //Fix non-escaped backslashes - sql_query = sql_query.replace(/\\/g, '\\\\'); - new_clause = new_clause.substring(0, new_clause.length-5); - new_clause = PMA_urlencode(new_clause); - sql_query += ' WHERE ' + PMA_urldecode(where_clause); - // Avoid updating more than one row in case there is no primary key - // (happened only for duplicate rows) - sql_query += ' LIMIT 1'; - /** - * @var rel_fields_list String, url encoded representation of {@link relations_fields} - */ - var rel_fields_list = $.param(relation_fields); + /** + * @var transform_fields_list String, url encoded representation of {@link transform_fields} + */ + var transform_fields_list = $.param(transform_fields); - /** - * @var transform_fields_list String, url encoded representation of {@link transform_fields} - */ - var transform_fields_list = $.param(transform_fields); - - if (need_to_post) { // Make the Ajax post after setting all parameters /** * @var post_params Object containing parameters for the POST request @@ -984,34 +944,127 @@ 'submit_type' : 'save' }; + $(g.cEdit).find('*').attr('disabled', true); var $editArea = $(g.cEdit).find('.edit_area'); $editArea.addClass('edit_area_posting'); - $(g.cEdit).find('*').attr('disabled', true); - - $.post('tbl_replace.php', post_params, function(data) { - $editArea.removeClass('edit_area_posting'); - if(data.success == true) { - PMA_ajaxShowMessage(data.message); - if (new_clause != '') { - $this_field.parent('tr').find('.where_clause').attr('value', new_clause); + + $.ajax({ + type: 'POST', + url: 'tbl_replace.php', + data: post_params, + context: $this_field[0], + success: + function(data) { + $editArea.removeClass('edit_area_posting'); + if(data.success == true) { + PMA_ajaxShowMessage(data.message); + if (new_clause != '') { + $this_field.parent('tr').find('.where_clause').attr('value', new_clause); + } + // remove possible previous feedback message + $('#result_query').remove(); + if (typeof data.sql_query != 'undefined') { + // display feedback + $('#sqlqueryresults').prepend(data.sql_query); + } + g.hideEditCell(true, data, this); + } else { + PMA_ajaxShowMessage(data.error); + } } - // remove possible previous feedback message - $('#result_query').remove(); - if (typeof data.sql_query != 'undefined') { - // display feedback - $('#sqlqueryresults').prepend(data.sql_query); - } - //PMA_unInlineEditRow($del_hide, $chg_submit, $this_field, $input_siblings, data); - g.hideEditCell(true, data); - } else { - PMA_ajaxShowMessage(data.error); - }; }) // end $.post() + }); // end of $('to_be_saved').each() + + $('.save_edited').hide(); + }, + + // save edited cell, so it can be posted later + saveEditedCell: function() { + /** + * @var $this_field Object referring to the td that is being edited + */ + var $this_field = $(g.currentEditCell); + var $test_element = ''; // to test the presence of a element + + var need_to_post = false; + + /** + * @var field_name String containing the name of this field. + * @see getFieldName() + */ + var field_name = getFieldName($this_field); + + /** + * @var this_field_params Array temporary storage for the name/value of current field + */ + var this_field_params = {}; + + /** + * @var is_null String capturing whether 'checkbox_null__' is checked. + */ + var is_null = $(g.cEdit).find('input:checkbox').is(':checked'); + var value; + + if (is_null) { + if (!g.wasEditedCellNull) { + this_field_params[field_name] = null; + need_to_post = true; + } } else { - // no posting was done but still need to display the row - // in its previous format - //PMA_unInlineEditRow($del_hide, $chg_submit, $this_field, $input_siblings, ''); - g.hideEditCell(); + if($this_field.is(":not(.relation, .enum, .set, .bit)")) { + this_field_params[field_name] = $(g.cEdit).find('textarea').val(); + } else if ($this_field.is('.bit')) { + this_field_params[field_name] = '0b' + $(g.cEdit).find('textarea').val(); + } else if ($this_field.is('.set')) { + $test_element = $(g.cEdit).find('select'); + this_field_params[field_name] = $test_element.map(function(){ + return $(this).val(); + }).get().join(","); + } else { + // results from a drop-down + $test_element = $(g.cEdit).find('select'); + if ($test_element.length != 0) { + this_field_params[field_name] = $test_element.val(); + } + + // results from Browse foreign value + $test_element = $(g.cEdit).find('span.curr_value'); + if ($test_element.length != 0) { + this_field_params[field_name] = $test_element.text(); + } + } + if (g.wasEditedCellNull || this_field_params[field_name] != PMA_getCellValue(g.currentEditCell)) { + need_to_post = true; + } + } + + if (need_to_post) { + $(g.currentEditCell).addClass('to_be_saved') + .data('value', this_field_params[field_name]); + if (g.saveCellsAtOnce) { + $('.save_edited').show(); + } + g.isCellEdited = true; + } + + return need_to_post; + }, + + // save or post edited cell, depending on the configuration + saveOrPostEditedCell: function() { + var saved = g.saveEditedCell(); + if (!g.saveCellsAtOnce) { + if (saved) { + g.postEditedCell(); + } else { + g.hideEditCell(true); + } + } else { + if (saved) { + g.hideEditCell(true, true); + } else { + g.hideEditCell(true); + } } } } @@ -1078,6 +1131,10 @@ // assign cell editing hint g.cellEditHint = $('#cell_edit_hint').val(); + g.saveCellWarning = $('#save_cell_warning').val(); + + // initialize cell editing configuration + g.saveCellsAtOnce = $('#save_cells_at_once').val(); // initialize column order $col_order = $('#col_order'); @@ -1251,7 +1308,7 @@ $(t).find('td.data') .click(function(e) { if (g.isCellEditActive) { - g.postEditedCell(); + g.saveOrPostEditedCell(); e.stopPropagation(); } else { g.showEditCell(this); @@ -1269,7 +1326,7 @@ if (e.which == 13) { // post on pressing "Enter" e.preventDefault(); - g.postEditedCell(); + g.saveOrPostEditedCell(); } }); $(g.cEdit).keydown(function(e) { @@ -1286,10 +1343,18 @@ }); $('html').keydown(function(e) { if (e.which == 27 && g.isCellEditActive) { + // cancel on pressing "Esc" g.hideEditCell(true); } }); + $('.save_edited').click(function() { + g.postEditedCell(); + }); + $(window).bind('beforeunload', function(e) { + return g.isCellEdited ? g.saveCellWarning : null; + }); + // add table class $(t).addClass('pma_table'); diff --git a/libraries/config.default.php b/libraries/config.default.php index 5762531d73..a626a28b02 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -2312,6 +2312,11 @@ $cfg['ShowBrowseComments'] = true; */ $cfg['ShowPropertyComments']= true; +/** + * save edited cell(s) in browse-mode at once. + */ +$cfg['SaveCellsAtOnce'] = false; + /** * shows table display direction. */ diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php index 5d42f89c86..96e903ef24 100644 --- a/libraries/config/messages.inc.php +++ b/libraries/config/messages.inc.php @@ -354,6 +354,7 @@ $strConfigRepeatCells_name = __('Repeat headers'); $strConfigReplaceHelpImg_desc = __('Show help button instead of Documentation text'); $strConfigReplaceHelpImg_name = __('Show help button'); $strConfigRestoreDefaultValue = __('Restore default value'); +$strConfigSaveCellsAtOnce_name = __('Save all edited cells at once'); $strConfigSaveDir_desc = __('Directory where exports can be saved on server'); $strConfigSaveDir_name = __('Save directory'); $strConfigServers_AllowDeny_order_desc = __('Leave blank if not used'); diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php index 5598b93786..32e8e4ab5c 100644 --- a/libraries/config/setup.forms.php +++ b/libraries/config/setup.forms.php @@ -198,6 +198,7 @@ $forms['Main_frame']['Browse'] = array( 'Order', 'BrowsePointerEnable', 'BrowseMarkerEnable', + 'SaveCellsAtOnce', 'ShowDisplayDirection', 'RepeatCells', 'LimitChars', diff --git a/libraries/config/user_preferences.forms.php b/libraries/config/user_preferences.forms.php index 8dc78feaa9..671e77584d 100644 --- a/libraries/config/user_preferences.forms.php +++ b/libraries/config/user_preferences.forms.php @@ -108,6 +108,7 @@ $forms['Main_frame']['Browse'] = array( 'DisplayBinaryAsHex', 'BrowsePointerEnable', 'BrowseMarkerEnable', + 'SaveCellsAtOnce', 'ShowDisplayDirection', 'RepeatCells', 'LimitChars', diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index 3ed305b2cb..1d4b6b2951 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -390,11 +390,13 @@ function PMA_displayTableNavigation($pos_next, $pos_prev, $sql_query, $id_for_di } ?> -
- +
+
+ '; ?> '; ?> + '; ?>
From 338552b21d583e416dfb2310e2bfce381916f25c Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Tue, 26 Jul 2011 18:32:46 +0800 Subject: [PATCH 18/57] Grid edit: change cfg['SaveCellsAtOnce'] default to true --- libraries/config.default.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/config.default.php b/libraries/config.default.php index a626a28b02..9d827c516c 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -2315,7 +2315,7 @@ $cfg['ShowPropertyComments']= true; /** * save edited cell(s) in browse-mode at once. */ -$cfg['SaveCellsAtOnce'] = false; +$cfg['SaveCellsAtOnce'] = true; /** * shows table display direction. From 92385de0feed4c3962cd9a23c2689d81284baced Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Wed, 27 Jul 2011 17:43:13 +0800 Subject: [PATCH 19/57] Grid edit: one query to save all edited cells at once --- js/makegrid.js | 344 ++++++++++++++++++++++++++----------------------- 1 file changed, 183 insertions(+), 161 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 9d9aab1986..5fe73e5833 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -814,168 +814,190 @@ * Post the content of edited cell. */ postEditedCell: function() { - $('.to_be_saved').each(function() { - /** - * @var $this_field Object referring to the td that is being edited - */ - var $this_field = $(this); - - // remove the to_be_saved class - $this_field.removeClass('to_be_saved'); - - var $test_element = ''; // to test the presence of a element - - // Initialize variables - var where_clause = $this_field.parent('tr').find('.where_clause').val(); - - /** - * @var nonunique Boolean, whether this row is unique or not - */ - var nonunique = $this_field.is('.nonunique') ? 0 : 1; - /** - * @var relation_fields Array containing the name/value pairs of relational fields - */ - var relation_fields = {}; - /** - * @var relational_display string 'K' if relational key, 'D' if relational display column - */ - var relational_display = $("#relational_display_K").attr('checked') ? 'K' : 'D'; - /** - * @var transform_fields Array containing the name/value pairs for transformed fields - */ - var transform_fields = {}; - /** - * @var transformation_fields Boolean, if there are any transformed fields in this row - */ - var transformation_fields = false; - - /** - * @var sql_query String containing the SQL query to update this row - */ - var sql_query = 'UPDATE `' + window.parent.table + '` SET '; - - var new_clause = ''; - - /** - * @var field_name String containing the name of this field. - * @see getFieldName() - */ - var field_name = getFieldName($this_field); - - /** - * @var this_field_params Array temporary storage for the name/value of current field - */ - var this_field_params = {}; - - if($this_field.is('.transformed')) { - transformation_fields = true; - } - /** - * @var is_null String capturing whether 'checkbox_null__' is checked. - */ - var is_null = $this_field.data('value') == null; - var value; - var addQuotes = true; - - if (is_null) { - sql_query += ' `' + field_name + "`=NULL , "; - } else { - this_field_params[field_name] = $this_field.data('value'); - if($this_field.is(":not(.relation, .enum, .set, .bit)")) { - if($this_field.is('.transformed')) { - $.extend(transform_fields, this_field_params); - } - } else if ($this_field.is('.bit')) { - addQuotes = false; - } else if($this_field.is('.relation')) { - $.extend(relation_fields, this_field_params); - } - if (where_clause.indexOf(field_name) > -1) { - new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND '; - } - if (addQuotes == true) { - sql_query += ' `' + field_name + "`='" + this_field_params[field_name].replace(/'/g, "''") + "', "; - } else { - sql_query += ' `' + field_name + "`=" + this_field_params[field_name].replace(/'/g, "''") + ", "; - } - } - - /* - * update the where_clause, remove the last appended ' AND ' - * */ - - //Remove the last ',' appended in the above loop - sql_query = sql_query.replace(/,\s$/, ''); - //Fix non-escaped backslashes - sql_query = sql_query.replace(/\\/g, '\\\\'); - new_clause = new_clause.substring(0, new_clause.length-5); - new_clause = PMA_urlencode(new_clause); - sql_query += ' WHERE ' + PMA_urldecode(where_clause); - // Avoid updating more than one row in case there is no primary key - // (happened only for duplicate rows) - sql_query += ' LIMIT 1'; - /** - * @var rel_fields_list String, url encoded representation of {@link relations_fields} - */ - var rel_fields_list = $.param(relation_fields); - - /** - * @var transform_fields_list String, url encoded representation of {@link transform_fields} - */ - var transform_fields_list = $.param(transform_fields); - - // Make the Ajax post after setting all parameters - /** - * @var post_params Object containing parameters for the POST request - */ - var post_params = {'ajax_request' : true, - 'sql_query' : sql_query, - 'token' : window.parent.token, - 'server' : window.parent.server, - 'db' : window.parent.db, - 'table' : window.parent.table, - 'clause_is_unique' : nonunique, - 'where_clause' : where_clause, - 'rel_fields_list' : rel_fields_list, - 'do_transformations' : transformation_fields, - 'transform_fields_list' : transform_fields_list, - 'relational_display' : relational_display, - 'goto' : 'sql.php', - 'submit_type' : 'save' - }; - - $(g.cEdit).find('*').attr('disabled', true); - var $editArea = $(g.cEdit).find('.edit_area'); - $editArea.addClass('edit_area_posting'); - - $.ajax({ - type: 'POST', - url: 'tbl_replace.php', - data: post_params, - context: $this_field[0], - success: - function(data) { - $editArea.removeClass('edit_area_posting'); - if(data.success == true) { - PMA_ajaxShowMessage(data.message); - if (new_clause != '') { - $this_field.parent('tr').find('.where_clause').attr('value', new_clause); - } - // remove possible previous feedback message - $('#result_query').remove(); - if (typeof data.sql_query != 'undefined') { - // display feedback - $('#sqlqueryresults').prepend(data.sql_query); - } - g.hideEditCell(true, data, this); - } else { - PMA_ajaxShowMessage(data.error); - } - } - }) // end $.post() - }); // end of $('to_be_saved').each() + /** + * @var relation_fields Array containing the name/value pairs of relational fields + */ + var relation_fields = {}; + /** + * @var relational_display string 'K' if relational key, 'D' if relational display column + */ + var relational_display = $("#relational_display_K").attr('checked') ? 'K' : 'D'; + /** + * @var transform_fields Array containing the name/value pairs for transformed fields + */ + var transform_fields = {}; + /** + * @var transformation_fields Boolean, if there are any transformed fields in the edited cells + */ + var transformation_fields = false; + /** + * @var full_sql_query String containing the complete SQL query to update this table + */ + var full_sql_query = ''; + /** + * @var rel_fields_list String, url encoded representation of {@link relations_fields} + */ + var rel_fields_list = ''; + /** + * @var transform_fields_list String, url encoded representation of {@link transform_fields} + */ + var transform_fields_list = ''; + /** + * @var where_clause Array containing where clause for updated fields + */ + var full_where_clause = Array(); + /** + * @var nonunique Boolean, whether the rows in this table is unique or not + */ + var nonunique = $('.to_be_saved').is('.nonunique') ? 0 : 1; + /** + * multi edit variables + */ + var me_fields_name = Array(); + var me_fields = Array(); - $('.save_edited').hide(); + // loop each edited row + $('.to_be_saved').parents('tr').each(function() { + var where_clause = $(this).find('.where_clause').val(); + full_where_clause.push(unescape(where_clause.replace(/[+]/g, ' '))); + var new_clause = ''; + + /** + * multi edit variables, for current row + * @TODO array indices are still not correct, they should be md5 of field's name + */ + var fields_name = Array(); + var fields = Array(); + + // loop each edited cell in a row + $(this).find('.to_be_saved').each(function() { + /** + * @var $this_field Object referring to the td that is being edited + */ + var $this_field = $(this); + + var $test_element = ''; // to test the presence of a element + + /** + * @var field_name String containing the name of this field. + * @see getFieldName() + */ + var field_name = getFieldName($this_field); + + /** + * @var this_field_params Array temporary storage for the name/value of current field + */ + var this_field_params = {}; + + if($this_field.is('.transformed')) { + transformation_fields = true; + } + /** + * @var is_null String capturing whether 'checkbox_null__' is checked. + */ + var is_null = $this_field.data('value') == null; + var value; + var addQuotes = true; + + fields_name.push(field_name); + fields.push($this_field.data('value')); + + if (!is_null) { + this_field_params[field_name] = $this_field.data('value'); + if($this_field.is(":not(.relation, .enum, .set, .bit)")) { + if($this_field.is('.transformed')) { + $.extend(transform_fields, this_field_params); + } + } else if ($this_field.is('.bit')) { + addQuotes = false; + } else if($this_field.is('.relation')) { + $.extend(relation_fields, this_field_params); + } + if (where_clause.indexOf(field_name) > -1) { + new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND '; + } + } + + /* + * update the where_clause, remove the last appended ' AND ' + * */ + + // prepare and save new_clause + new_clause = new_clause.substring(0, new_clause.length-5); + new_clause = PMA_urlencode(new_clause); + $this_field.parent('tr').data('new_clause', new_clause); + + rel_fields_list += $.param(relation_fields) + '&'; + transform_fields_list += $.param(transform_fields) + '&'; + + }); // end of loop for every edited cells in a row + + me_fields_name.push(fields_name); + me_fields.push(fields); + + }); // end of loop for every edited rows + + // Make the Ajax post after setting all parameters + /** + * @var post_params Object containing parameters for the POST request + */ + var post_params = {'ajax_request' : true, + 'sql_query' : full_sql_query, + 'token' : window.parent.token, + 'server' : window.parent.server, + 'db' : window.parent.db, + 'table' : window.parent.table, + 'clause_is_unique' : nonunique, + 'where_clause' : full_where_clause, + 'fields[multi_edit]' : me_fields, + 'fields_name[multi_edit]' : me_fields_name, + 'rel_fields_list' : rel_fields_list, + 'do_transformations' : transformation_fields, + 'transform_fields_list' : transform_fields_list, + 'relational_display' : relational_display, + 'goto' : 'sql.php', + 'submit_type' : 'save' + }; + + $(g.cEdit).find('*').attr('disabled', true); + var $editArea = $(g.cEdit).find('.edit_area'); + $editArea.addClass('edit_area_posting'); + + $.ajax({ + type: 'POST', + url: 'tbl_replace.php', + data: post_params, + context: $this_field[0], + success: + function(data) { + $editArea.removeClass('edit_area_posting'); + if(data.success == true) { + PMA_ajaxShowMessage(data.message); + $('.to_be_saved').each(function() { + var new_clause = $(this).parent('tr').data('new_clause'); + if (new_clause != '') { + $(this).parent('tr').find('.where_clause').attr('value', new_clause); + } + }); + // remove possible previous feedback message + $('#result_query').remove(); + if (typeof data.sql_query != 'undefined') { + // display feedback + $('#sqlqueryresults').prepend(data.sql_query); + } + g.hideEditCell(true, data, this); + + // remove the "Save edited cells" button + $('.save_edited').hide(); + // remove the to_be_saved class + $('.to_be_saved').removeClass('to_be_saved'); + + g.isCellEdited = false; + } else { + PMA_ajaxShowMessage(data.error); + } + } + }) // end $.ajax() }, // save edited cell, so it can be posted later From 685db48a794815b45dad5197194c1d0c3a6c8e6a Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Wed, 27 Jul 2011 17:49:40 +0800 Subject: [PATCH 20/57] Grid edit: fix bug - edited cell not saved when clicking on 'Save edited data' button, while the edit area still shown --- js/makegrid.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/makegrid.js b/js/makegrid.js index 5fe73e5833..6fd1301ae8 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1371,6 +1371,7 @@ } }); $('.save_edited').click(function() { + g.hideEditCell(); g.postEditedCell(); }); $(window).bind('beforeunload', function(e) { From a6850dd0892b7144e70af6b847066de7ca085465 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 28 Jul 2011 10:18:45 +0800 Subject: [PATCH 21/57] Grid edit: fix bug - is not defined when cfg['SaveCellsAtOnce'] is false --- js/makegrid.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 6fd1301ae8..0d504adc00 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -967,7 +967,6 @@ type: 'POST', url: 'tbl_replace.php', data: post_params, - context: $this_field[0], success: function(data) { $editArea.removeClass('edit_area_posting'); @@ -985,7 +984,7 @@ // display feedback $('#sqlqueryresults').prepend(data.sql_query); } - g.hideEditCell(true, data, this); + g.hideEditCell(true, data); // remove the "Save edited cells" button $('.save_edited').hide(); From 0e55c083a9583b013b8a5c8c97743b5b9f8a9152 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 28 Jul 2011 16:46:51 +0800 Subject: [PATCH 22/57] Grid edit: update relation and transformation correctly --- js/makegrid.js | 95 +++++++++++++++---------------------- tbl_replace.php | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 57 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 0d504adc00..06aa5746b9 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -515,63 +515,45 @@ g.isCellEditActive = false; if (data) { - $this_field = field == undefined ? $(g.currentEditCell) : $(field); - $this_field_span = $this_field.children('span'); - - var is_null = $this_field.data('value') == null; - if (is_null) { - $this_field_span.html('NULL'); - $this_field.addClass('null'); - } else { - $this_field.removeClass('null'); - /** - * @var new_html String containing value of the data field after edit - */ + if (data === true) { + // replace current edited field with the new value + var $this_field = $(g.currentEditCell); var new_html = $this_field.data('value'); - - if($this_field.is(':not(.relation, .enum, .set)')) { - if($this_field.is('.transformed')) { - var field_name = getFieldName($this_field); - if (typeof data.transformations != 'undefined') { - $.each(data.transformations, function(key, value) { - if(key == field_name) { - if($this_field.is('.text_plain, .application_octetstream')) { - new_html = value; - return false; - } else { - var new_value = $this_field.data('value'); - new_html = $(value).append(new_value); - return false; - } - } - }) - } - } else if ($this_field.is('.truncated')) { + var is_null = $this_field.data('value') == null; + if (is_null) { + $this_field_span.html('NULL'); + $this_field.addClass('null'); + } else { + $this_field.removeClass('null'); + if ($this_field.is('.truncated')) { if (new_html.length > g.maxTruncatedLen) { new_html = new_html.substring(0, g.maxTruncatedLen) + '...'; } } // replace '\n' with
new_html = new_html.replace(/\n/g, '
'); - } else { - if($this_field.is('.relation')) { - var field_name = getFieldName($this_field); - if (typeof data.relations != 'undefined') { - $.each(data.relations, function(key, value) { - if(key == field_name) { - new_html = $(value); - return false; - } - }) - } - } } - $this_field_span.html(new_html); + $this_field.find('span').html(new_html); + } else { + // update edited fields with new value from "data" + if (data.transformations != undefined) { + $.each(data.transformations, function(cell_index, value) { + var $this_field = $(g.t).find('.to_be_saved:eq(' + cell_index + ')'); + $this_field.find('span').html(value); + }); + } + if (data.relations != undefined) { + $.each(data.relations, function(cell_index, value) { + var $this_field = $(g.t).find('.to_be_saved:eq(' + cell_index + ')'); + $this_field.find('span').html(value); + }); + } } + // refresh the grid this.reposRsz(); this.reposDrop(); - } // end of if "data" is defined, i.e. post successful + } }, /** @@ -896,22 +878,22 @@ * @var is_null String capturing whether 'checkbox_null__' is checked. */ var is_null = $this_field.data('value') == null; - var value; - var addQuotes = true; fields_name.push(field_name); fields.push($this_field.data('value')); - + if (!is_null) { this_field_params[field_name] = $this_field.data('value'); + + var cell_index = $this_field.index('.to_be_saved'); if($this_field.is(":not(.relation, .enum, .set, .bit)")) { if($this_field.is('.transformed')) { - $.extend(transform_fields, this_field_params); + transform_fields[cell_index] = {}; + $.extend(transform_fields[cell_index], this_field_params); } - } else if ($this_field.is('.bit')) { - addQuotes = false; } else if($this_field.is('.relation')) { - $.extend(relation_fields, this_field_params); + relation_fields[cell_index] = {}; + $.extend(relation_fields[cell_index], this_field_params); } if (where_clause.indexOf(field_name) > -1) { new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND '; @@ -926,10 +908,6 @@ new_clause = new_clause.substring(0, new_clause.length-5); new_clause = PMA_urlencode(new_clause); $this_field.parent('tr').data('new_clause', new_clause); - - rel_fields_list += $.param(relation_fields) + '&'; - transform_fields_list += $.param(transform_fields) + '&'; - }); // end of loop for every edited cells in a row me_fields_name.push(fields_name); @@ -937,6 +915,9 @@ }); // end of loop for every edited rows + rel_fields_list = $.param(relation_fields); + transform_fields_list = $.param(transform_fields); + // Make the Ajax post after setting all parameters /** * @var post_params Object containing parameters for the POST request @@ -989,7 +970,7 @@ // remove the "Save edited cells" button $('.save_edited').hide(); // remove the to_be_saved class - $('.to_be_saved').removeClass('to_be_saved'); + $(g.t).find('.to_be_saved').removeClass('to_be_saved'); g.isCellEdited = false; } else { diff --git a/tbl_replace.php b/tbl_replace.php index 48d01fc6de..75d041d81d 100644 --- a/tbl_replace.php +++ b/tbl_replace.php @@ -405,6 +405,127 @@ if (! empty($error_messages)) { unset($error_messages, $warning_messages, $total_affected_rows, $last_messages, $last_message); if ($GLOBALS['is_ajax_request'] == true) { + /** + * If we are in grid editing, we need to process the relational and + * transformed fields, if they were edited. After that, output the correct + * link/transformed value and exit + * + * Logic taken from libraries/display_tbl.lib.php + */ + + if (isset($_REQUEST['rel_fields_list']) && $_REQUEST['rel_fields_list'] != '') { + //handle relations work here for updated row. + require_once './libraries/relation.lib.php'; + + $map = PMA_getForeigners($db, $table, '', 'both'); + + $rel_fields = array(); + parse_str($_REQUEST['rel_fields_list'], $rel_fields); + + // loop for each relation cell + foreach ( $rel_fields as $cell_index => $curr_cell_rel_field) { + + foreach ( $curr_cell_rel_field as $rel_field => $rel_field_value) { + + $where_comparison = "='" . $rel_field_value . "'"; + $display_field = PMA_getDisplayField($map[$rel_field]['foreign_db'], $map[$rel_field]['foreign_table']); + + // Field to display from the foreign table? + if (isset($display_field) && strlen($display_field)) { + $dispsql = 'SELECT ' . PMA_backquote($display_field) + . ' FROM ' . PMA_backquote($map[$rel_field]['foreign_db']) + . '.' . PMA_backquote($map[$rel_field]['foreign_table']) + . ' WHERE ' . PMA_backquote($map[$rel_field]['foreign_field']) + . $where_comparison; + $dispresult = PMA_DBI_try_query($dispsql, null, PMA_DBI_QUERY_STORE); + if ($dispresult && PMA_DBI_num_rows($dispresult) > 0) { + list($dispval) = PMA_DBI_fetch_row($dispresult, 0); + } else { + //$dispval = __('Link not found'); + } + @PMA_DBI_free_result($dispresult); + } else { + $dispval = ''; + } // end if... else... + + if ('K' == $_SESSION['tmp_user_values']['relational_display']) { + // user chose "relational key" in the display options, so + // the title contains the display field + $title = (! empty($dispval))? ' title="' . htmlspecialchars($dispval) . '"' : ''; + } else { + $title = ' title="' . htmlspecialchars($rel_field_value) . '"'; + } + + $_url_params = array( + 'db' => $map[$rel_field]['foreign_db'], + 'table' => $map[$rel_field]['foreign_table'], + 'pos' => '0', + 'sql_query' => 'SELECT * FROM ' + . PMA_backquote($map[$rel_field]['foreign_db']) . '.' . PMA_backquote($map[$rel_field]['foreign_table']) + . ' WHERE ' . PMA_backquote($map[$rel_field]['foreign_field']) + . $where_comparison + ); + $output = ''; + + if ('D' == $_SESSION['tmp_user_values']['relational_display']) { + // user chose "relational display field" in the + // display options, so show display field in the cell + $output .= (!empty($dispval)) ? htmlspecialchars($dispval) : ''; + } else { + // otherwise display data in the cell + $output .= htmlspecialchars($rel_field_value); + } + $output .= ''; + $extra_data['relations'][$cell_index] = $output; + } + } // end of loop for each relation cell + } + + if (isset($_REQUEST['do_transformations']) && $_REQUEST['do_transformations'] == true ) { + require_once './libraries/transformations.lib.php'; + //if some posted fields need to be transformed, generate them here. + $mime_map = PMA_getMIME($db, $table); + + if ($mime_map === false) { + $mime_map = array(); + } + + $edited_values = array(); + parse_str($_REQUEST['transform_fields_list'], $edited_values); + + foreach($mime_map as $transformation) { + $include_file = PMA_securePath($transformation['transformation']); + $column_name = $transformation['column_name']; + + foreach ($edited_values as $cell_index => $curr_cell_edited_values) { + if (isset($curr_cell_edited_values[$column_name])) { + $column_data = $curr_cell_edited_values[$column_name]; + + $_url_params = array( + 'db' => $db, + 'table' => $table, + 'where_clause' => $_REQUEST['where_clause'], + 'transform_key' => $column_name, + ); + + if (file_exists('./libraries/transformations/' . $include_file)) { + $transformfunction_name = str_replace('.inc.php', '', $transformation['transformation']); + + require_once './libraries/transformations/' . $include_file; + + if (function_exists('PMA_transformation_' . $transformfunction_name)) { + $transform_function = 'PMA_transformation_' . $transformfunction_name; + $transform_options = PMA_transformation_getOptions((isset($transformation['transformation_options']) ? $transformation['transformation_options'] : '')); + $transform_options['wrapper_link'] = PMA_generate_common_url($_url_params); + } + } + + $extra_data['transformations'][$cell_index] = $transform_function($column_data, $transform_options); + } + } // end of loop for each transformation cell + } // end of loop for each $mime_map + } + /**Get the total row count of the table*/ $extra_data['row_count'] = PMA_Table::countRecords($_REQUEST['db'],$_REQUEST['table']); $extra_data['sql_query'] = PMA_showMessage(NULL, $GLOBALS['display_query']); From d1c219b94eecf70b34fba9715ac6f5279c761c91 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 28 Jul 2011 17:45:59 +0800 Subject: [PATCH 23/57] Grid edit: modification checking for TEXT data type --- js/functions.js | 2 ++ js/makegrid.js | 96 ++++++++++++++++++++++++++++++------------------- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/js/functions.js b/js/functions.js index 8c858882c3..77d6373800 100644 --- a/js/functions.js +++ b/js/functions.js @@ -2981,6 +2981,8 @@ function PMA_createqTip($elements, content, options) { function PMA_getCellValue(td) { if ($(td).is('.null')) { return ''; + } else if ($(td).data('original_data')) { + return $(td).data('original_data'); } else if ($(td).is(':not(.transformed, .relation, .enum, .set, .null)')) { return unescape($(td).find('span').html()).replace(/
/g, "\n"); } else { diff --git a/js/makegrid.js b/js/makegrid.js index 06aa5746b9..e8f82b9acf 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -738,43 +738,62 @@ }) } else if($td.is('.truncated, .transformed')) { - /** @lends jQuery */ - //handle truncated/transformed values values - $editArea.addClass('edit_area_loading'); + if ($td.is('.to_be_saved')) { // cell has been edited + var value = $td.data('value'); + $(g.cEdit).find('input[type=text]').val(value); + $editArea.append(''); + $editArea.find('textarea').live('keyup', function(e) { + $(g.cEdit).find('input[type=text]').val($(this).val()); + }); + $(g.cEdit).find('input[type=text]').live('keyup', function(e) { + $editArea.find('textarea').val($(this).val()); + }); + $editArea.append('
' + g.cellEditHint + '
'); + } else { + /** @lends jQuery */ + //handle truncated/transformed values values + $editArea.addClass('edit_area_loading'); - /** - * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data - */ - var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause); + // initialize the original data + $td.data('original_data', null); - // Make the Ajax call and get the data, wrap it and insert it - $.post('sql.php', { - 'token' : window.parent.token, - 'server' : window.parent.server, - 'db' : window.parent.db, - 'ajax_request' : true, - 'sql_query' : sql_query, - 'inline_edit' : true - }, function(data) { - $editArea.removeClass('edit_area_loading'); - if(data.success == true) { - // get the truncated data length - g.maxTruncatedLen = PMA_getCellValue(g.currentEditCell).length - 3; - - $(g.cEdit).find('input[type=text]').val(data.value); - $editArea.append(''); - $editArea.find('textarea').live('keyup', function(e) { - $(g.cEdit).find('input[type=text]').val($(this).val()); - }); - $(g.cEdit).find('input[type=text]').live('keyup', function(e) { - $editArea.find('textarea').val($(this).val()); - }); - $editArea.append('
' + g.cellEditHint + '
'); - } - else { - PMA_ajaxShowMessage(data.error); - } - }) // end $.post() + /** + * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data + */ + var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause); + + // Make the Ajax call and get the data, wrap it and insert it + $.post('sql.php', { + 'token' : window.parent.token, + 'server' : window.parent.server, + 'db' : window.parent.db, + 'ajax_request' : true, + 'sql_query' : sql_query, + 'inline_edit' : true + }, function(data) { + $editArea.removeClass('edit_area_loading'); + if(data.success == true) { + if ($td.is('.truncated')) { + // get the truncated data length + g.maxTruncatedLen = $(g.currentEditCell).text().length - 3; + } + + $td.data('original_data', data.value); + $(g.cEdit).find('input[type=text]').val(data.value); + $editArea.append(''); + $editArea.find('textarea').live('keyup', function(e) { + $(g.cEdit).find('input[type=text]').val($(this).val()); + }); + $(g.cEdit).find('input[type=text]').live('keyup', function(e) { + $editArea.find('textarea').val($(this).val()); + }); + $editArea.append('
' + g.cellEditHint + '
'); + } + else { + PMA_ajaxShowMessage(data.error); + } + }) // end $.post() + } g.isEditCellTextEditable = true; } else { $editArea.append(''); @@ -969,8 +988,11 @@ // remove the "Save edited cells" button $('.save_edited').hide(); - // remove the to_be_saved class - $(g.t).find('.to_be_saved').removeClass('to_be_saved'); + // update saved fields + $(g.t).find('.to_be_saved') + .removeClass('to_be_saved') + .data('value', null) + .data('original_data', null); g.isCellEdited = false; } else { From 8d0138cfb67168f5f2849e1ffeadf0a5d4710d62 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 28 Jul 2011 17:54:21 +0800 Subject: [PATCH 24/57] Grid edit: better modification checking for relation field, when 'Relational display column' is chosen --- js/makegrid.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/js/makegrid.js b/js/makegrid.js index e8f82b9acf..a7aee649fb 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -655,6 +655,9 @@ //handle relations $editArea.addClass('edit_area_loading'); + // initialize the original data + $td.data('original_data', null); + /** * @var post_params Object containing parameters for the POST request */ @@ -672,6 +675,12 @@ $.post('sql.php', post_params, function(data) { $editArea.removeClass('edit_area_loading'); + // save original_data + var value = $(data.dropdown).val(); + $td.data('original_data', value); + // update the text input field, in case where the "Relational display column" is checked + $(g.cEdit).find('input[type=text]').val(value); + $editArea.append(data.dropdown); $editArea.append('
' + g.cellEditHint + '
'); }) // end $.post() From a752c74d59b88cb40fa35ca9681e305974cd0ade Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 28 Jul 2011 18:05:32 +0800 Subject: [PATCH 25/57] Grid edit: better AJAX request handling --- js/makegrid.js | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index a7aee649fb..5651453f14 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -32,6 +32,7 @@ saveCellsAtOnce: false, // $cfg[saveCellsAtOnce] isCellEdited: false, // true if at least one cell has been edited saveCellWarning: '', // string, warning text when user want to leave a page with unsaved edited data + lastXHR : null, // last XHR object used in AJAX request // functions dragStartRsz: function(e, obj) { // start column resize @@ -510,6 +511,14 @@ g.saveOrPostEditedCell(); return; } + + // cancel any previous request + if (g.lastXHR != null) { + g.lastXHR.abort(); + g.lastXHR = null; + } + + // hide the cell editing area $(g.cEdit).hide(); $(g.cEdit).find('input[type=text]').blur(); g.isCellEditActive = false; @@ -673,7 +682,7 @@ 'relation_key_or_display_column' : relation_key_or_display_column } - $.post('sql.php', post_params, function(data) { + g.lastXHR = $.post('sql.php', post_params, function(data) { $editArea.removeClass('edit_area_loading'); // save original_data var value = $(data.dropdown).val(); @@ -707,7 +716,7 @@ 'token' : window.parent.token, 'curr_value' : curr_value } - $.post('sql.php', post_params, function(data) { + g.lastXHR = $.post('sql.php', post_params, function(data) { $editArea.removeClass('edit_area_loading'); $editArea.append(data.dropdown); $editArea.append('
' + g.cellEditHint + '
'); @@ -736,7 +745,7 @@ 'curr_value' : curr_value } - $.post('sql.php', post_params, function(data) { + g.lastXHR = $.post('sql.php', post_params, function(data) { $editArea.removeClass('edit_area_loading'); $editArea.append(data.select); $editArea.append('
' + g.cellEditHint + '
'); @@ -772,7 +781,7 @@ var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause); // Make the Ajax call and get the data, wrap it and insert it - $.post('sql.php', { + g.lastXHR = $.post('sql.php', { 'token' : window.parent.token, 'server' : window.parent.server, 'db' : window.parent.db, From d5054f6775f2389af32171cef835ba1fc7a4fa55 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 28 Jul 2011 18:17:17 +0800 Subject: [PATCH 26/57] Grid edit: add loading indicator when saving data --- js/makegrid.js | 18 ++++++++++++++---- themes/original/css/theme_right.css.php | 5 +++++ themes/pmahomme/css/theme_right.css.php | 5 +++++ 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 5651453f14..6599672bf7 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -977,9 +977,14 @@ 'submit_type' : 'save' }; - $(g.cEdit).find('*').attr('disabled', true); - var $editArea = $(g.cEdit).find('.edit_area'); - $editArea.addClass('edit_area_posting'); + if (!g.saveCellsAtOnce) { + $(g.cEdit).find('*').attr('disabled', true); + var $editArea = $(g.cEdit).find('.edit_area'); + $editArea.addClass('edit_area_posting'); + } else { + $('.save_edited').addClass('saving_edited_data') + .attr('disabled', true); + } $.ajax({ type: 'POST', @@ -987,7 +992,12 @@ data: post_params, success: function(data) { - $editArea.removeClass('edit_area_posting'); + if (!g.saveCellsAtOnce) { + $editArea.removeClass('edit_area_posting'); + } else { + $('.save_edited').removeClass('saving_edited_data') + .attr('disabled', false); + } if(data.success == true) { PMA_ajaxShowMessage(data.message); $('.to_be_saved').each(function() { diff --git a/themes/original/css/theme_right.css.php b/themes/original/css/theme_right.css.php index bf3b2b8429..ec1d8fc89f 100644 --- a/themes/original/css/theme_right.css.php +++ b/themes/original/css/theme_right.css.php @@ -2505,3 +2505,8 @@ span.mysql-number { padding: 0.2em 0.3em; } +.saving_edited_data { + background: url(./themes/pmahomme/img/ajax_clock_small.gif) no-repeat left; + padding-left: 20px; +} + diff --git a/themes/pmahomme/css/theme_right.css.php b/themes/pmahomme/css/theme_right.css.php index 4e51172ad7..f1a3872da1 100644 --- a/themes/pmahomme/css/theme_right.css.php +++ b/themes/pmahomme/css/theme_right.css.php @@ -2944,3 +2944,8 @@ span.mysql-number { padding: 0.2em 0.3em; } +.saving_edited_data { + background: url(./themes/pmahomme/img/ajax_clock_small.gif) no-repeat left; + padding-left: 20px; +} + From e1da98ae8551e2ffcc925481231ee95d2f9954c5 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 11:43:00 +0800 Subject: [PATCH 27/57] Grid edit: fix bug - notice line above SQL query now shown correctly --- tbl_replace.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tbl_replace.php b/tbl_replace.php index 75d041d81d..22bf81349c 100644 --- a/tbl_replace.php +++ b/tbl_replace.php @@ -528,7 +528,7 @@ if ($GLOBALS['is_ajax_request'] == true) { /**Get the total row count of the table*/ $extra_data['row_count'] = PMA_Table::countRecords($_REQUEST['db'],$_REQUEST['table']); - $extra_data['sql_query'] = PMA_showMessage(NULL, $GLOBALS['display_query']); + $extra_data['sql_query'] = PMA_showMessage($message, $GLOBALS['display_query']); PMA_ajaxResponse($message, $message->isSuccess(), $extra_data); } From 351afca2c70d1e91ce65990d5f64bf1da0601af9 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 12:48:39 +0800 Subject: [PATCH 28/57] Grid edit: null-related things --- js/makegrid.js | 18 +++++++++++++----- libraries/tbl_replace_fields.inc.php | 2 +- tbl_replace.php | 4 ++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 6599672bf7..cc72920468 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -530,7 +530,7 @@ var new_html = $this_field.data('value'); var is_null = $this_field.data('value') == null; if (is_null) { - $this_field_span.html('NULL'); + $this_field.find('span').html('NULL'); $this_field.addClass('null'); } else { $this_field.removeClass('null'); @@ -541,8 +541,8 @@ } // replace '\n' with
new_html = new_html.replace(/\n/g, '
'); + $this_field.find('span').html(new_html); } - $this_field.find('span').html(new_html); } else { // update edited fields with new value from "data" if (data.transformations != undefined) { @@ -874,6 +874,7 @@ */ var me_fields_name = Array(); var me_fields = Array(); + var me_fields_null = Array(); // loop each edited row $('.to_be_saved').parents('tr').each(function() { @@ -887,6 +888,7 @@ */ var fields_name = Array(); var fields = Array(); + var fields_null = Array(); // loop each edited cell in a row $(this).find('.to_be_saved').each(function() { @@ -914,12 +916,16 @@ /** * @var is_null String capturing whether 'checkbox_null__' is checked. */ - var is_null = $this_field.data('value') == null; + var is_null = $this_field.data('value') === null; fields_name.push(field_name); - fields.push($this_field.data('value')); - if (!is_null) { + if (is_null) { + fields_null.push('on'); + fields.push(''); + } else { + fields_null.push(''); + fields.push($this_field.data('value')); this_field_params[field_name] = $this_field.data('value'); var cell_index = $this_field.index('.to_be_saved'); @@ -949,6 +955,7 @@ me_fields_name.push(fields_name); me_fields.push(fields); + me_fields_null.push(fields_null); }); // end of loop for every edited rows @@ -969,6 +976,7 @@ 'where_clause' : full_where_clause, 'fields[multi_edit]' : me_fields, 'fields_name[multi_edit]' : me_fields_name, + 'fields_null[multi_edit]' : me_fields_null, 'rel_fields_list' : rel_fields_list, 'do_transformations' : transformation_fields, 'transform_fields_list' : transform_fields_list, diff --git a/libraries/tbl_replace_fields.inc.php b/libraries/tbl_replace_fields.inc.php index 32da9c085d..f1a0b9ed02 100644 --- a/libraries/tbl_replace_fields.inc.php +++ b/libraries/tbl_replace_fields.inc.php @@ -95,7 +95,7 @@ if (false !== $possibly_uploaded_val) { // Was the Null checkbox checked for this field? // (if there is a value, we ignore the Null checkbox: this could // be possible if Javascript is disabled in the browser) - if (isset($me_fields_null[$key]) + if (! empty($me_fields_null[$key]) && ($val == "''" || $val == '')) { $val = 'NULL'; } diff --git a/tbl_replace.php b/tbl_replace.php index 22bf81349c..08750e43d8 100644 --- a/tbl_replace.php +++ b/tbl_replace.php @@ -271,8 +271,8 @@ foreach ($loop_array as $rownumber => $where_clause) { // avoid setting a field to NULL when it's already NULL // (field had the null checkbox before the update // field still has the null checkbox) - if (!(! empty($me_fields_null_prev[$key]) - && isset($me_fields_null[$key]))) { + if (empty($me_fields_null_prev[$key]) + || empty($me_fields_null[$key])) { $query_values[] = PMA_backquote($me_fields_name[$key]) . ' = ' . $cur_value; } } From 8f08c0283d5cecf338a6747ab832330cdbd2ecef Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 14:41:28 +0800 Subject: [PATCH 29/57] Grid edit: correctly update the WHERE clause --- js/makegrid.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index cc72920468..3756f777ad 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -880,7 +880,7 @@ $('.to_be_saved').parents('tr').each(function() { var where_clause = $(this).find('.where_clause').val(); full_where_clause.push(unescape(where_clause.replace(/[+]/g, ' '))); - var new_clause = ''; + var new_clause = where_clause; /** * multi edit variables, for current row @@ -939,17 +939,13 @@ $.extend(relation_fields[cell_index], this_field_params); } if (where_clause.indexOf(field_name) > -1) { - new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND '; + var old_sub_clause_regex = new RegExp(PMA_urlencode('`' + window.parent.table + '`.' + '`' + field_name + '`') + '[+]%3D[+][^+]*'); + var new_sub_clause = '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'"; + new_clause = new_clause.replace(old_sub_clause_regex, new_sub_clause); } } - /* - * update the where_clause, remove the last appended ' AND ' - * */ - - // prepare and save new_clause - new_clause = new_clause.substring(0, new_clause.length-5); - new_clause = PMA_urlencode(new_clause); + // save new_clause $this_field.parent('tr').data('new_clause', new_clause); }); // end of loop for every edited cells in a row @@ -1011,7 +1007,13 @@ $('.to_be_saved').each(function() { var new_clause = $(this).parent('tr').data('new_clause'); if (new_clause != '') { - $(this).parent('tr').find('.where_clause').attr('value', new_clause); + var $where_clause = $(this).parent('tr').find('.where_clause'); + var old_clause = $where_clause.attr('value'); + $where_clause.attr('value', new_clause); + // update Edit, Copy, and Delete links also + $(this).parent('tr').find('a').each(function() { + $(this).attr('href', $(this).attr('href').replace(old_clause, new_clause)); + }); } }); // remove possible previous feedback message From 926f5950a97154bf8028641b60af6bceb0ba6dbe Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 14:43:00 +0800 Subject: [PATCH 30/57] Grid edit: detect nonunique class --- js/makegrid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/makegrid.js b/js/makegrid.js index 3756f777ad..700a32c0aa 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -868,7 +868,7 @@ /** * @var nonunique Boolean, whether the rows in this table is unique or not */ - var nonunique = $('.to_be_saved').is('.nonunique') ? 0 : 1; + var nonunique = $('.inline_edit_anchor').is('.nonunique') ? 0 : 1; /** * multi edit variables */ From ac1703e7ff720ebb95dbf7af0331219bbcb6ab17 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 15:58:28 +0800 Subject: [PATCH 31/57] Grid edit: fix for WHERE clause handling --- js/makegrid.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 700a32c0aa..5264effe2e 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -938,9 +938,11 @@ relation_fields[cell_index] = {}; $.extend(relation_fields[cell_index], this_field_params); } - if (where_clause.indexOf(field_name) > -1) { - var old_sub_clause_regex = new RegExp(PMA_urlencode('`' + window.parent.table + '`.' + '`' + field_name + '`') + '[+]%3D[+][^+]*'); - var new_sub_clause = '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'"; + if (where_clause.indexOf(PMA_urlencode(field_name)) > -1) { + var fields_str = PMA_urlencode('`' + window.parent.table + '`.' + '`' + field_name + '` = '); + fields_str = fields_str.replace(/[+]/g, '[+]'); // replace '+' sign with '[+]' (regex) + var old_sub_clause_regex = new RegExp(fields_str + '[^+]*'); + var new_sub_clause = PMA_urlencode('`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'"); new_clause = new_clause.replace(old_sub_clause_regex, new_sub_clause); } } From 1e2f73c6e90c95747a668d7f6b24ed6b61df65cc Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 16:14:06 +0800 Subject: [PATCH 32/57] Fix bug: PMA_urlencode didn't encode space character correctly --- js/sql.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/sql.js b/js/sql.js index e762bb53c0..a1072fd117 100644 --- a/js/sql.js +++ b/js/sql.js @@ -20,7 +20,7 @@ function PMA_urldecode(str) { } function PMA_urlencode(str) { - return encodeURIComponent(str.replace(/\%20/g, '+')); + return encodeURIComponent(str).replace(/\%20/g, '+'); } /** From 8ae900a3f894cdd8215fc6a73873d6d2ee16385f Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 17:01:16 +0800 Subject: [PATCH 33/57] Grid edit: fix bug - alert everytime leave Browse page --- js/makegrid.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/makegrid.js b/js/makegrid.js index 5264effe2e..21042171f6 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1417,7 +1417,9 @@ g.postEditedCell(); }); $(window).bind('beforeunload', function(e) { - return g.isCellEdited ? g.saveCellWarning : null; + if (g.isCellEdited) { + g.saveCellWarning; + } }); // add table class From c2790e11958adcb97a7d7579a7ad8ed4bfdf8b69 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 17:12:42 +0800 Subject: [PATCH 34/57] Grid edit: fix disabled state --- js/makegrid.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 21042171f6..22da282b62 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -488,7 +488,7 @@ g.isCellEditActive = false; g.currentEditCell = cell; $(g.cEdit).find('input[type=text]').focus(); - $(g.cEdit).find('*').attr('disabled', false); + $(g.cEdit).find('*').removeAttr('disabled'); } } else { g.hideEditCell(); @@ -984,12 +984,12 @@ }; if (!g.saveCellsAtOnce) { - $(g.cEdit).find('*').attr('disabled', true); + $(g.cEdit).find('*').attr('disabled', 'disabled'); var $editArea = $(g.cEdit).find('.edit_area'); $editArea.addClass('edit_area_posting'); } else { $('.save_edited').addClass('saving_edited_data') - .attr('disabled', true); + .find('input').attr('disabled', 'disabled'); // disable the save button } $.ajax({ @@ -1002,7 +1002,7 @@ $editArea.removeClass('edit_area_posting'); } else { $('.save_edited').removeClass('saving_edited_data') - .attr('disabled', false); + .find('input').removeAttr('disabled'); // enable the save button back } if(data.success == true) { PMA_ajaxShowMessage(data.message); From 5cf1288f91e314288e362ed6834c76acac2c13d2 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 17:59:55 +0800 Subject: [PATCH 35/57] Grid edit: 2 fixes - update edited field correctly when SaveCellsAtOnce is false; enable edit field after save AJAX request is complete --- js/makegrid.js | 105 +++++++++++++++++++--------------- libraries/display_tbl.lib.php | 7 +++ 2 files changed, 66 insertions(+), 46 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 22da282b62..bcd4ef78b1 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -34,6 +34,12 @@ saveCellWarning: '', // string, warning text when user want to leave a page with unsaved edited data lastXHR : null, // last XHR object used in AJAX request + // common hidden inputs + token: null, + server: null, + db: null, + table: null, + // functions dragStartRsz: function(e, obj) { // start column resize var n = $(this.cRsz).find('div').index(obj); @@ -284,10 +290,10 @@ sendColPrefs: function() { $.post('sql.php', { ajax_request: true, - db: window.parent.db, - table: window.parent.table, - token: window.parent.token, - server: window.parent.server, + db: g.db, + table: g.table, + token: g.token, + server: g.server, set_col_prefs: true, col_order: this.colOrder.toString(), col_visib: this.colVisib.toString(), @@ -518,13 +524,8 @@ g.lastXHR = null; } - // hide the cell editing area - $(g.cEdit).hide(); - $(g.cEdit).find('input[type=text]').blur(); - g.isCellEditActive = false; - if (data) { - if (data === true) { + if (g.currentEditCell) { // save value of currently edited cell // replace current edited field with the new value var $this_field = $(g.currentEditCell); var new_html = $this_field.data('value'); @@ -543,26 +544,30 @@ new_html = new_html.replace(/\n/g, '
'); $this_field.find('span').html(new_html); } - } else { - // update edited fields with new value from "data" - if (data.transformations != undefined) { - $.each(data.transformations, function(cell_index, value) { - var $this_field = $(g.t).find('.to_be_saved:eq(' + cell_index + ')'); - $this_field.find('span').html(value); - }); - } - if (data.relations != undefined) { - $.each(data.relations, function(cell_index, value) { - var $this_field = $(g.t).find('.to_be_saved:eq(' + cell_index + ')'); - $this_field.find('span').html(value); - }); - } + } + if (data.transformations != undefined) { + $.each(data.transformations, function(cell_index, value) { + var $this_field = $(g.t).find('.to_be_saved:eq(' + cell_index + ')'); + $this_field.find('span').html(value); + }); + } + if (data.relations != undefined) { + $.each(data.relations, function(cell_index, value) { + var $this_field = $(g.t).find('.to_be_saved:eq(' + cell_index + ')'); + $this_field.find('span').html(value); + }); } // refresh the grid this.reposRsz(); this.reposDrop(); } + + // hide the cell editing area + $(g.cEdit).hide(); + $(g.cEdit).find('input[type=text]').blur(); + g.isCellEditActive = false; + g.currentEditCell = null; }, /** @@ -673,11 +678,11 @@ var post_params = { 'ajax_request' : true, 'get_relational_values' : true, - 'server' : window.parent.server, - 'db' : window.parent.db, - 'table' : window.parent.table, + 'server' : g.server, + 'db' : g.db, + 'table' : g.table, 'column' : field_name, - 'token' : window.parent.token, + 'token' : g.token, 'curr_value' : relation_curr_value, 'relation_key_or_display_column' : relation_key_or_display_column } @@ -709,11 +714,11 @@ var post_params = { 'ajax_request' : true, 'get_enum_values' : true, - 'server' : window.parent.server, - 'db' : window.parent.db, - 'table' : window.parent.table, + 'server' : g.server, + 'db' : g.db, + 'table' : g.table, 'column' : field_name, - 'token' : window.parent.token, + 'token' : g.token, 'curr_value' : curr_value } g.lastXHR = $.post('sql.php', post_params, function(data) { @@ -737,11 +742,11 @@ var post_params = { 'ajax_request' : true, 'get_set_values' : true, - 'server' : window.parent.server, - 'db' : window.parent.db, - 'table' : window.parent.table, + 'server' : g.server, + 'db' : g.db, + 'table' : g.table, 'column' : field_name, - 'token' : window.parent.token, + 'token' : g.token, 'curr_value' : curr_value } @@ -778,13 +783,13 @@ /** * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data */ - var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause); + var sql_query = 'SELECT `' + field_name + '` FROM `' + g.table + '` WHERE ' + PMA_urldecode(where_clause); // Make the Ajax call and get the data, wrap it and insert it g.lastXHR = $.post('sql.php', { - 'token' : window.parent.token, - 'server' : window.parent.server, - 'db' : window.parent.db, + 'token' : g.token, + 'server' : g.server, + 'db' : g.db, 'ajax_request' : true, 'sql_query' : sql_query, 'inline_edit' : true @@ -939,10 +944,10 @@ $.extend(relation_fields[cell_index], this_field_params); } if (where_clause.indexOf(PMA_urlencode(field_name)) > -1) { - var fields_str = PMA_urlencode('`' + window.parent.table + '`.' + '`' + field_name + '` = '); + var fields_str = PMA_urlencode('`' + g.table + '`.' + '`' + field_name + '` = '); fields_str = fields_str.replace(/[+]/g, '[+]'); // replace '+' sign with '[+]' (regex) var old_sub_clause_regex = new RegExp(fields_str + '[^+]*'); - var new_sub_clause = PMA_urlencode('`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'"); + var new_sub_clause = PMA_urlencode('`' + g.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'"); new_clause = new_clause.replace(old_sub_clause_regex, new_sub_clause); } } @@ -966,10 +971,10 @@ */ var post_params = {'ajax_request' : true, 'sql_query' : full_sql_query, - 'token' : window.parent.token, - 'server' : window.parent.server, - 'db' : window.parent.db, - 'table' : window.parent.table, + 'token' : g.token, + 'server' : g.server, + 'db' : g.db, + 'table' : g.table, 'clause_is_unique' : nonunique, 'where_clause' : full_where_clause, 'fields[multi_edit]' : me_fields, @@ -999,6 +1004,7 @@ success: function(data) { if (!g.saveCellsAtOnce) { + $(g.cEdit).find('*').removeAttr('disabled'); $editArea.removeClass('edit_area_posting'); } else { $('.save_edited').removeClass('saving_edited_data') @@ -1200,6 +1206,13 @@ // initialize cell editing configuration g.saveCellsAtOnce = $('#save_cells_at_once').val(); + // assign common hidden inputs + var $common_hidden_inputs = $('.common_hidden_inputs'); + g.token = $common_hidden_inputs.find('input[name=token]').val(); + g.server = $common_hidden_inputs.find('input[name=server]').val(); + g.db = $common_hidden_inputs.find('input[name=db]').val(); + g.table = $common_hidden_inputs.find('input[name=table]').val(); + // initialize column order $col_order = $('#col_order'); if ($col_order.length > 0) { diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index 472fbebbd9..cfb7cc6e78 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -397,6 +397,13 @@ function PMA_displayTableNavigation($pos_next, $pos_prev, $sql_query, $id_for_di '; ?> '; ?> '; ?> + '; + echo PMA_generate_common_hidden_inputs($db, $table); + echo '
'; + ?>
From 4f5d6a59aaff7ba27b43df8beed7ed94d96dbafa Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 18:11:33 +0800 Subject: [PATCH 36/57] Grid edit: fix bug - wrong update on isCellEditActive value --- js/makegrid.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index bcd4ef78b1..417e0ead8f 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -491,7 +491,6 @@ $(g.cEdit).find('input') .val(value); - g.isCellEditActive = false; g.currentEditCell = cell; $(g.cEdit).find('input[type=text]').focus(); $(g.cEdit).find('*').removeAttr('disabled'); @@ -513,7 +512,6 @@ hideEditCell: function(force, data, field) { if (g.isCellEditActive && !force) { // cell is being edited, post the edited data - g.isCellEditActive = false; g.saveOrPostEditedCell(); return; } From 0d197603085c43cac543351795b3df6de4167b96 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 29 Jul 2011 18:18:30 +0800 Subject: [PATCH 37/57] Fix bug in qTip when updating content using qTip API in IE --- js/jquery/jquery.qtip-1.0.0-rc3.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/jquery/jquery.qtip-1.0.0-rc3.js b/js/jquery/jquery.qtip-1.0.0-rc3.js index 5b9c7e3064..4b01d9dbca 100644 --- a/js/jquery/jquery.qtip-1.0.0-rc3.js +++ b/js/jquery/jquery.qtip-1.0.0-rc3.js @@ -633,6 +633,7 @@ { // Set width to auto initally to determine new width and hide other elements self.elements.tooltip.css({ width: 'auto' }); + self.elements.wrapper.css({ width: 'auto' }); hidden.hide(); // Set position and zoom to defaults to prevent IE hasLayout bug @@ -2146,4 +2147,4 @@ classes: { tooltip: 'qtip-blue' } } }; -})(jQuery); \ No newline at end of file +})(jQuery); From 080e0b6d00b926744470be3090ec7cd2f4546ff1 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 1 Aug 2011 17:11:08 +0800 Subject: [PATCH 38/57] Grid edit: fix bug - alert not shown when leaving edited page --- js/makegrid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/makegrid.js b/js/makegrid.js index 417e0ead8f..20819e8200 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1429,7 +1429,7 @@ }); $(window).bind('beforeunload', function(e) { if (g.isCellEdited) { - g.saveCellWarning; + return g.saveCellWarning; } }); From 03503c914bb49eb6a94ef25f9aea61df7eefff30 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 1 Aug 2011 17:21:07 +0800 Subject: [PATCH 39/57] Grid edit: fix bug - Clicking on other place while grid edit still loading, make the field become NULL, if it is NULLABLE --- js/makegrid.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/js/makegrid.js b/js/makegrid.js index 20819e8200..41f1d9e627 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1073,7 +1073,9 @@ var is_null = $(g.cEdit).find('input:checkbox').is(':checked'); var value; - if (is_null) { + if ($(g.cEdit).find('.edit_area').is('.edit_area_loading')) { + need_to_post = false; + } else if (is_null) { if (!g.wasEditedCellNull) { this_field_params[field_name] = null; need_to_post = true; From 8eff621a152b16462211882adca99c66b507c92c Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Tue, 2 Aug 2011 10:20:41 +0800 Subject: [PATCH 40/57] Fix bug - duplicate ID in some data and text for makegrid.js --- js/makegrid.js | 14 ++++----- js/messages.php | 10 +++++++ libraries/display_tbl.lib.php | 56 ++++++++++++++--------------------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 41f1d9e627..d8a8818bd1 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1193,15 +1193,15 @@ g.tableCreateTime = $('#table_create_time').val(); // assign column reorder & column sort hint - g.reorderHint = $('#col_order_hint').val(); - g.sortHint = $('#sort_hint').val(); - g.markHint = $('#col_mark_hint').val(); - g.colVisibHint = $('#col_visib_hint').val(); - g.showAllColText = $('#show_all_col_text').val(); + g.reorderHint = PMA_messages['strColOrderHint']; + g.sortHint = PMA_messages['strSortHint']; + g.markHint = PMA_messages['strColMarkHint']; + g.colVisibHint = PMA_messages['strColVisibHint']; + g.showAllColText = PMA_messages['strShowAllCol']; // assign cell editing hint - g.cellEditHint = $('#cell_edit_hint').val(); - g.saveCellWarning = $('#save_cell_warning').val(); + g.cellEditHint = PMA_messages['strCellEditHint']; + g.saveCellWarning = PMA_messages['strSaveCellWarning']; // initialize cell editing configuration g.saveCellsAtOnce = $('#save_cells_at_once').val(); diff --git a/js/messages.php b/js/messages.php index 357e745dd8..187c87323e 100644 --- a/js/messages.php +++ b/js/messages.php @@ -227,6 +227,15 @@ $js_messages['strLeavingDesigner'] = __('You haven\'t saved the changes in the l /* Visual query builder (pmd/scripts/move.js) */ $js_messages['strAddOption'] = __('Add an option for column '); +/* For makegrid.js (column reordering, show/hide column, grid editing) */ +$js_messages['strCellEditHint'] = __('Press escape to cancel editing'); +$js_messages['strSaveCellWarning'] = __('You have edited some data and they have not been saved. Are you sure you want to leave this page before saving the data?'); +$js_messages['strColOrderHint'] = __('Drag to reorder'); +$js_messages['strSortHint'] = __('Click to sort'); +$js_messages['strColMarkHint'] = __('Click to mark/unmark'); +$js_messages['strColVisibHint'] = __('Click the drop-down arrow
to toggle column\'s visibility'); +$js_messages['strShowAllCol'] = __('Show all'); + /* password generation */ $js_messages['strGeneratePassword'] = __('Generate password'); $js_messages['strGenerate'] = __('Generate'); @@ -241,6 +250,7 @@ $js_messages['strNewerVersion'] = __('A newer version of phpMyAdmin is available $js_messages['strLatestAvailable'] = __(', latest stable version:'); $js_messages['strUpToDate'] = __('up to date'); + echo "var PMA_messages = new Array();\n"; foreach ($js_messages as $name => $js_message) { PMA_printJsValue("PMA_messages['" . $name . "']", $js_message); diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index cfb7cc6e78..d1d635d544 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -394,45 +394,12 @@ function PMA_displayTableNavigation($pos_next, $pos_prev, $sql_query, $id_for_di
- '; ?> - '; ?> - '; ?> - '; - echo PMA_generate_common_hidden_inputs($db, $table); - echo '
'; - ?>
- getUiProp(PMA_Table::PROP_COLUMN_ORDER); - if ($col_order) { - echo ''; - } - $col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB); - if ($col_visib) { - echo ''; - } - // generate table create time - echo ''; - } - // generate hints - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - ?> '; + echo '
'; + echo PMA_generate_common_hidden_inputs($db, $table); + echo '
'; + // Output data needed for column reordering and show/hide column + if (PMA_isSelect()) { + // generate the column order, if it is set + $pmatable = new PMA_Table($GLOBALS['table'], $GLOBALS['db']); + $col_order = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_ORDER); + if ($col_order) { + echo ''; + } + $col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB); + if ($col_visib) { + echo ''; + } + // generate table create time + echo ''; + } + + $vertical_display['emptypre'] = 0; $vertical_display['emptyafter'] = 0; $vertical_display['textbtn'] = ''; From 5f154503d00f94a2247e370455e0b720ef8526a8 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Tue, 2 Aug 2011 13:02:05 +0800 Subject: [PATCH 41/57] Grid edit: fix bug - (1) update delete confirmation message after grid editing, (2) change wrongly named variable, 'nonunique', copied from inline edit code --- js/makegrid.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 417e0ead8f..81ee236481 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -869,9 +869,9 @@ */ var full_where_clause = Array(); /** - * @var nonunique Boolean, whether the rows in this table is unique or not + * @var is_unique Boolean, whether the rows in this table is unique or not */ - var nonunique = $('.inline_edit_anchor').is('.nonunique') ? 0 : 1; + var is_unique = $('.inline_edit_anchor').is('.nonunique') ? 0 : 1; /** * multi edit variables */ @@ -973,7 +973,7 @@ 'server' : g.server, 'db' : g.db, 'table' : g.table, - 'clause_is_unique' : nonunique, + 'clause_is_unique' : is_unique, 'where_clause' : full_where_clause, 'fields[multi_edit]' : me_fields, 'fields_name[multi_edit]' : me_fields_name, @@ -1019,6 +1019,15 @@ // update Edit, Copy, and Delete links also $(this).parent('tr').find('a').each(function() { $(this).attr('href', $(this).attr('href').replace(old_clause, new_clause)); + // update delete confirmation in Delete link + if ($(this).attr('href').indexOf('DELETE') > -1) { + $(this).removeAttr('onclick') + .unbind('click') + .bind('click', function() { + return confirmLink(this, 'DELETE FROM `' + g.db + '`.`' + g.table + '` WHERE ' + + PMA_urldecode(new_clause) + (is_unique ? '' : ' LIMIT 1')); + }); + } }); } }); From 65bea22f1faa7dda9ffa9bd04d00b7fb47a01907 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Tue, 2 Aug 2011 13:07:25 +0800 Subject: [PATCH 42/57] Grid edit: fix bug - multi rows edit not work correctly on grid edited rows, if the primary key changed (case if there is a primary key) or some field changed (case if there is no primary key) --- js/makegrid.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/js/makegrid.js b/js/makegrid.js index 81ee236481..e24c39ade8 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1015,6 +1015,9 @@ if (new_clause != '') { var $where_clause = $(this).parent('tr').find('.where_clause'); var old_clause = $where_clause.attr('value'); + var decoded_old_clause = PMA_urldecode(old_clause); + var decoded_new_clause = PMA_urldecode(new_clause); + $where_clause.attr('value', new_clause); // update Edit, Copy, and Delete links also $(this).parent('tr').find('a').each(function() { @@ -1025,10 +1028,19 @@ .unbind('click') .bind('click', function() { return confirmLink(this, 'DELETE FROM `' + g.db + '`.`' + g.table + '` WHERE ' + - PMA_urldecode(new_clause) + (is_unique ? '' : ' LIMIT 1')); + decoded_new_clause + (is_unique ? '' : ' LIMIT 1')); }); } }); + // update the multi edit checkboxes + $(this).parent('tr').find('input[type=checkbox]').each(function() { + var $checkbox = $(this); + var checkbox_name = $checkbox.attr('name'); + var checkbox_value = $checkbox.attr('value'); + + $checkbox.attr('name', checkbox_name.replace(old_clause, new_clause)); + $checkbox.attr('value', checkbox_value.replace(decoded_old_clause, decoded_new_clause)); + }); } }); // remove possible previous feedback message From 91d85841fc015665a8e8d3c4bfb7d2140ca41f5c Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Wed, 3 Aug 2011 10:21:41 +0800 Subject: [PATCH 43/57] Grid edit: fix bug - update where_clause precisely (previous version cannot handle space or special characters) --- js/makegrid.js | 42 ++++++++++++++++++----------- libraries/common.lib.php | 50 ++++++++++++++++++++++------------- libraries/display_tbl.lib.php | 21 ++++++++------- 3 files changed, 70 insertions(+), 43 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index e24c39ade8..8b9e46e19b 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -881,9 +881,10 @@ // loop each edited row $('.to_be_saved').parents('tr').each(function() { - var where_clause = $(this).find('.where_clause').val(); + var $tr = $(this); + var where_clause = $tr.find('.where_clause').val(); full_where_clause.push(unescape(where_clause.replace(/[+]/g, ' '))); - var new_clause = where_clause; + var condition_array = jQuery.parseJSON($tr.find('.condition_array').val()); /** * multi edit variables, for current row @@ -894,14 +895,12 @@ var fields_null = Array(); // loop each edited cell in a row - $(this).find('.to_be_saved').each(function() { + $tr.find('.to_be_saved').each(function() { /** * @var $this_field Object referring to the td that is being edited */ var $this_field = $(this); - var $test_element = ''; // to test the presence of a element - /** * @var field_name String containing the name of this field. * @see getFieldName() @@ -916,10 +915,12 @@ if($this_field.is('.transformed')) { transformation_fields = true; } + this_field_params[field_name] = $this_field.data('value'); + /** * @var is_null String capturing whether 'checkbox_null__' is checked. */ - var is_null = $this_field.data('value') === null; + var is_null = this_field_params[field_name] === null; fields_name.push(field_name); @@ -929,7 +930,6 @@ } else { fields_null.push(''); fields.push($this_field.data('value')); - this_field_params[field_name] = $this_field.data('value'); var cell_index = $this_field.index('.to_be_saved'); if($this_field.is(":not(.relation, .enum, .set, .bit)")) { @@ -941,19 +941,31 @@ relation_fields[cell_index] = {}; $.extend(relation_fields[cell_index], this_field_params); } - if (where_clause.indexOf(PMA_urlencode(field_name)) > -1) { - var fields_str = PMA_urlencode('`' + g.table + '`.' + '`' + field_name + '` = '); - fields_str = fields_str.replace(/[+]/g, '[+]'); // replace '+' sign with '[+]' (regex) - var old_sub_clause_regex = new RegExp(fields_str + '[^+]*'); - var new_sub_clause = PMA_urlencode('`' + g.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'"); - new_clause = new_clause.replace(old_sub_clause_regex, new_sub_clause); + } + // check if edited field appears in WHERE clause + if (where_clause.indexOf(PMA_urlencode(field_name)) > -1) { + var field_str = '`' + g.table + '`.' + '`' + field_name + '`'; + for (var field in condition_array) { + if (field.indexOf(field_str) > -1) { + condition_array[field] = is_null ? 'IS NULL' : "= '" + this_field_params[field_name].replace(/'/g,"''") + "'"; + break; + } } } - // save new_clause - $this_field.parent('tr').data('new_clause', new_clause); }); // end of loop for every edited cells in a row + // save new_clause + var new_clause = ''; + for (var field in condition_array) { + new_clause += field + ' ' + condition_array[field] + ' AND '; + } + new_clause = new_clause.substring(0, new_clause.length - 5); // remove the last AND + new_clause = PMA_urlencode(new_clause); + $tr.data('new_clause', new_clause); + // save condition_array + $tr.find('.condition_array').val(JSON.stringify(condition_array)); + me_fields_name.push(fields_name); me_fields.push(fields); me_fields_null.push(fields_null); diff --git a/libraries/common.lib.php b/libraries/common.lib.php index 61f5aa6936..e2229c5b02 100644 --- a/libraries/common.lib.php +++ b/libraries/common.lib.php @@ -1890,9 +1890,15 @@ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force $unique_key = ''; $nonprimary_condition = ''; $preferred_condition = ''; + $primary_key_array = array(); + $unique_key_array = array(); + $nonprimary_condition_array = array(); + $condition_array = array(); for ($i = 0; $i < $fields_cnt; ++$i) { $condition = ''; + $con_key = ''; + $con_val = ''; $field_flags = PMA_DBI_field_flags($handle, $i); $meta = $fields_meta[$i]; @@ -1934,20 +1940,21 @@ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force // (also, the syntax "CONCAT(field) IS NULL" // that we need on the next "if" will work) if ($meta->type == 'real') { - $condition = ' CONCAT(' . PMA_backquote($meta->table) . '.' - . PMA_backquote($meta->orgname) . ') '; + $con_key = 'CONCAT(' . PMA_backquote($meta->table) . '.' + . PMA_backquote($meta->orgname) . ')'; } else { - $condition = ' ' . PMA_backquote($meta->table) . '.' - . PMA_backquote($meta->orgname) . ' '; + $con_key = PMA_backquote($meta->table) . '.' + . PMA_backquote($meta->orgname); } // end if... else... + $condition = ' ' . $con_key . ' '; if (! isset($row[$i]) || is_null($row[$i])) { - $condition .= 'IS NULL AND'; + $con_val = 'IS NULL'; } else { // timestamp is numeric on some MySQL 4.1 // for real we use CONCAT above and it should compare to string if ($meta->numeric && $meta->type != 'timestamp' && $meta->type != 'real') { - $condition .= '= ' . $row[$i] . ' AND'; + $con_val = '= ' . $row[$i]; } elseif (($meta->type == 'blob' || $meta->type == 'string') // hexify only if this is a true not empty BLOB or a BINARY && stristr($field_flags, 'BINARY') @@ -1956,25 +1963,29 @@ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force if (strlen($row[$i]) < 1000) { // use a CAST if possible, to avoid problems // if the field contains wildcard characters % or _ - $condition .= '= CAST(0x' . bin2hex($row[$i]) - . ' AS BINARY) AND'; + $con_val = '= CAST(0x' . bin2hex($row[$i]) . ' AS BINARY)'; } else { // this blob won't be part of the final condition - $condition = ''; + $con_val = null; } } elseif ($meta->type == 'bit') { - $condition .= "= b'" . PMA_printable_bit_value($row[$i], $meta->length) . "' AND"; + $con_val = "= b'" . PMA_printable_bit_value($row[$i], $meta->length) . "'"; } else { - $condition .= '= \'' - . PMA_sqlAddSlashes($row[$i], false, true) . '\' AND'; + $con_val = '= \'' . PMA_sqlAddSlashes($row[$i], false, true) . '\''; } } - if ($meta->primary_key > 0) { - $primary_key .= $condition; - } elseif ($meta->unique_key > 0) { - $unique_key .= $condition; + if ($con_val != null) { + $condition .= $con_val . ' AND'; + if ($meta->primary_key > 0) { + $primary_key .= $condition; + $primary_key_array[$con_key] = $con_val; + } elseif ($meta->unique_key > 0) { + $unique_key .= $condition; + $unique_key_array[$con_key] = $con_val; + } + $nonprimary_condition .= $condition; + $nonprimary_condition_array[$con_key] = $con_val; } - $nonprimary_condition .= $condition; } // end for // Correction University of Virginia 19991216: @@ -1983,15 +1994,18 @@ function PMA_getUniqueCondition($handle, $fields_cnt, $fields_meta, $row, $force $clause_is_unique = true; if ($primary_key) { $preferred_condition = $primary_key; + $condition_array = $primary_key_array; } elseif ($unique_key) { $preferred_condition = $unique_key; + $condition_array = $unique_key_array; } elseif (! $force_unique) { $preferred_condition = $nonprimary_condition; + $condition_array = $nonprimary_condition_array; $clause_is_unique = false; } $where_clause = trim(preg_replace('|\s?AND$|', '', $preferred_condition)); - return(array($where_clause, $clause_is_unique)); + return(array($where_clause, $clause_is_unique, $condition_array)); } // end function /** diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index cfb7cc6e78..fc57236269 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -1285,7 +1285,7 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { * with only one field and it's a BLOB; in this case, * avoid to display the delete and edit links */ - list($where_clause, $clause_is_unique) = PMA_getUniqueCondition($dt_result, $fields_cnt, $fields_meta, $row); + list($where_clause, $clause_is_unique, $condition_array) = PMA_getUniqueCondition($dt_result, $fields_cnt, $fields_meta, $row); $where_clause_html = urlencode($where_clause); // 1.2 Defines the URLs for the modify/delete link(s) @@ -1377,14 +1377,14 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { if (! isset($js_conf)) { $js_conf = ''; } - echo PMA_generateCheckboxAndLinks('left', $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $del_query, 'l', $edit_url, $copy_url, $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf); + echo PMA_generateCheckboxAndLinks('left', $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $condition_array, $del_query, 'l', $edit_url, $copy_url, $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf); } else if (($GLOBALS['cfg']['RowActionLinks'] == 'none') && ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped')) { if (! isset($js_conf)) { $js_conf = ''; } - echo PMA_generateCheckboxAndLinks('none', $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $del_query, 'l', $edit_url, $copy_url, $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf); + echo PMA_generateCheckboxAndLinks('none', $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $condition_array, $del_query, 'l', $edit_url, $copy_url, $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf); } // end if (1.3) } // end if (1) @@ -1669,7 +1669,7 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { if (! isset($js_conf)) { $js_conf = ''; } - echo PMA_generateCheckboxAndLinks('right', $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $del_query, 'r', $edit_url, $copy_url, $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf); + echo PMA_generateCheckboxAndLinks('right', $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $condition_array, $del_query, 'r', $edit_url, $copy_url, $edit_anchor_class, $edit_str, $copy_str, $del_str, $js_conf); } // end if (3) if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' @@ -1696,7 +1696,7 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { } if (!empty($del_url) && $is_display['del_lnk'] != 'kp') { - $vertical_display['row_delete'][$row_no] .= PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $del_query, '[%_PMA_CHECKBOX_DIR_%]', $alternating_color_class . $vertical_class); + $vertical_display['row_delete'][$row_no] .= PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $condition_array, $del_query, '[%_PMA_CHECKBOX_DIR_%]', $alternating_color_class . $vertical_class); } else { unset($vertical_display['row_delete'][$row_no]); } @@ -2711,7 +2711,7 @@ function PMA_prepare_row_data($class, $condition_field, $analyzed_sql, $meta, $m * @return string the generated HTML */ -function PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $del_query, $id_suffix, $class) { +function PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $condition_array, $del_query, $id_suffix, $class) { $ret = ''; if (! empty($del_url) && $is_display['del_lnk'] != 'kp') { $ret .= '' + . '' . ' '; } return $ret; @@ -2827,11 +2828,11 @@ function PMA_generateDeleteLink($del_url, $del_str, $js_conf, $class) { * @param string $js_conf * @return string the generated HTML */ -function PMA_generateCheckboxAndLinks($position, $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $del_query, $id_suffix, $edit_url, $copy_url, $class, $edit_str, $copy_str, $del_str, $js_conf) { +function PMA_generateCheckboxAndLinks($position, $del_url, $is_display, $row_no, $where_clause, $where_clause_html, $condition_array, $del_query, $id_suffix, $edit_url, $copy_url, $class, $edit_str, $copy_str, $del_str, $js_conf) { $ret = ''; if ($position == 'left') { - $ret .= PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $del_query, $id_suffix='_left', '', '', ''); + $ret .= PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $condition_array, $del_query, $id_suffix='_left', '', '', ''); $ret .= PMA_generateEditLink($edit_url, $class, $edit_str, $where_clause, $where_clause_html, ''); @@ -2846,9 +2847,9 @@ function PMA_generateCheckboxAndLinks($position, $del_url, $is_display, $row_no, $ret .= PMA_generateEditLink($edit_url, $class, $edit_str, $where_clause, $where_clause_html, ''); - $ret .= PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $del_query, $id_suffix='_right', '', '', ''); + $ret .= PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $condition_array, $del_query, $id_suffix='_right', '', '', ''); } else { // $position == 'none' - $ret .= PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $del_query, $id_suffix='_left', '', '', ''); + $ret .= PMA_generateCheckboxForMulti($del_url, $is_display, $row_no, $where_clause_html, $condition_array, $del_query, $id_suffix='_left', '', '', ''); } return $ret; } From 28a18c1727c9e89a47704cb3dacdcd832a61f3c0 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Wed, 3 Aug 2011 11:58:56 +0800 Subject: [PATCH 44/57] Grid edit: fix bug - not working if AjaxEnable set to false --- js/sql.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/js/sql.js b/js/sql.js index a1072fd117..1fa27cb18e 100644 --- a/js/sql.js +++ b/js/sql.js @@ -34,12 +34,13 @@ function getFieldName($this_field) { var this_field_index = $this_field.index(); // ltr or rtl direction does not impact how the DOM was generated // check if the action column in the left exist - var leftActionExist = !$('#table_results').find('th:first').hasClass('draggable'); - // 5 columns to account for the checkbox, edit, appended inline edit, copy and delete anchors but index is zero-based so substract 4 - var field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ') a').text(); + var left_action_exist = !$('#table_results').find('th:first').hasClass('draggable'); + // number of column span for checkbox and Actions + var left_action_skip = left_action_exist ? $('#table_results').find('th:first').attr('colspan') - 1 : 0; + var field_name = $('#table_results').find('thead').find('th:eq('+ (this_field_index - left_action_skip) + ') a').text(); // happens when just one row (headings contain no a) if ("" == field_name) { - field_name = $('#table_results').find('thead').find('th:nth('+ (this_field_index - (leftActionExist ? 4 : 0)) + ')').text(); + field_name = $('#table_results').find('thead').find('th:eq('+ (this_field_index - left_action_skip) + ')').text(); } field_name = $.trim(field_name); From 608f1a1cf0ac0944e9177a0679e63361759646a4 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 4 Aug 2011 11:57:00 +0800 Subject: [PATCH 45/57] Grid edit: fix bug - edited relational field not shown correctly when pulling the foreign key list --- js/functions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/functions.js b/js/functions.js index 77d6373800..eb1c9604f6 100644 --- a/js/functions.js +++ b/js/functions.js @@ -2981,7 +2981,7 @@ function PMA_createqTip($elements, content, options) { function PMA_getCellValue(td) { if ($(td).is('.null')) { return ''; - } else if ($(td).data('original_data')) { + } else if (! $(td).is('.to_be_saved') && $(td).data('original_data')) { return $(td).data('original_data'); } else if ($(td).is(':not(.transformed, .relation, .enum, .set, .null)')) { return unescape($(td).find('span').html()).replace(/
/g, "\n"); From 0e39df6ca4b2d9e129e301b9f17c5eb1d57ad851 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 4 Aug 2011 16:27:47 +0800 Subject: [PATCH 46/57] add configuration in 'user preferences' and 'setup' to show/hide the Hint created with PMA_createqTip function --- Documentation.html | 3 +++ js/functions.js | 3 +++ libraries/config.default.php | 7 +++++++ libraries/config/messages.inc.php | 2 ++ libraries/config/setup.forms.php | 1 + libraries/config/user_preferences.forms.php | 3 ++- libraries/header.inc.php | 6 ++++++ 7 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Documentation.html b/Documentation.html index 3f65223ce6..f10d03450f 100644 --- a/Documentation.html +++ b/Documentation.html @@ -1373,6 +1373,9 @@ CREATE DATABASE,ALTER DATABASE,DROP DATABASE main panel's list (except on the Export page). This limit is also enforced in the navigation panel when in Light mode.
+
$cfg['ShowHint'] boolean
+
Whether to show the hints or not (for example, hints when hovering table header)
+
$cfg['MaxCharactersInDisplayedSQL'] integer
The maximum number of characters when a SQL query is displayed. The default limit of 1000 should be correct to avoid the display of tons diff --git a/js/functions.js b/js/functions.js index 35f8e5664d..ca5fe811a7 100644 --- a/js/functions.js +++ b/js/functions.js @@ -2973,6 +2973,9 @@ $(document).ready(function() { * can be overriden by specifying optional "options" parameter (see qTip options). */ function PMA_createqTip($elements, content, options) { + if ($('#no_hint').length > 0) { + return; + } var o = { content: content, style: { diff --git a/libraries/config.default.php b/libraries/config.default.php index c1ff136118..7974adb252 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -543,6 +543,13 @@ $cfg['MaxDbList'] = 100; */ $cfg['MaxTableList'] = 250; +/** + * whether to show hint or not + * + * @global boolean $cfg['ShowHint'] + */ +$cfg['ShowHint'] = true; + /** * maximum number of characters when a SQL query is displayed * diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php index 96e903ef24..e16c8c63de 100644 --- a/libraries/config/messages.inc.php +++ b/libraries/config/messages.inc.php @@ -457,6 +457,8 @@ $strConfigShowFieldTypesInDataEditView_desc = __('Defines whether or not type fi $strConfigShowFieldTypesInDataEditView_name = __('Show field types'); $strConfigShowFunctionFields_desc = __('Display the function fields in edit/insert mode'); $strConfigShowFunctionFields_name = __('Show function fields'); +$strConfigShowHint_desc = __('Whether to show hint or not'); +$strConfigShowHint_name = __('Show hint'); $strConfigShowPhpInfo_desc = __('Shows link to [a@http://php.net/manual/function.phpinfo.php]phpinfo()[/a] output'); $strConfigShowPhpInfo_name = __('Show phpinfo() link'); $strConfigShowServerInfo_name = __('Show detailed MySQL server information'); diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php index a11df4da69..8b71eff7ec 100644 --- a/libraries/config/setup.forms.php +++ b/libraries/config/setup.forms.php @@ -130,6 +130,7 @@ $forms['Features']['Other_core_settings'] = array( 'ReplaceHelpImg', 'MaxDbList', 'MaxTableList', + 'ShowHint', 'OBGzip', 'PersistentConnections', 'ExecTimeLimit', diff --git a/libraries/config/user_preferences.forms.php b/libraries/config/user_preferences.forms.php index 671e77584d..7cefa4ac40 100644 --- a/libraries/config/user_preferences.forms.php +++ b/libraries/config/user_preferences.forms.php @@ -34,7 +34,8 @@ $forms['Features']['General'] = array( 'SkipLockedTables', 'DisableMultiTableMaintenance', 'MaxDbList', - 'MaxTableList'); + 'MaxTableList', + 'ShowHint'); $forms['Features']['Text_fields'] = array( 'CharEditing', 'CharTextareaCols', diff --git a/libraries/header.inc.php b/libraries/header.inc.php index a6ed8edc45..c42d90921e 100644 --- a/libraries/header.inc.php +++ b/libraries/header.inc.php @@ -96,6 +96,12 @@ if (isset($GLOBALS['is_ajax_request']) && !$GLOBALS['is_ajax_request']) { define('PMA_DISPLAY_HEADING', 1); } + // pass configuration for hint tooltip display + // (to be used by PMA_createqTip in js/functions.js) + if (! $GLOBALS['cfg']['ShowHint']) { + echo ''; + } + /** * Display heading if needed. Design can be set in css file. */ From 376cc353dcddbc7ed4568c6cc4ffdbad147bf15f Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Thu, 4 Aug 2011 18:27:37 +0800 Subject: [PATCH 47/57] Recent table: fix bug - not work for db or table name containing custom characters --- js/navigation.js | 6 +++--- libraries/RecentTable.class.php | 17 ++++++++++------- libraries/common.inc.php | 31 ++++++++++++++++--------------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/js/navigation.js b/js/navigation.js index 5ce805c278..33e829ce21 100644 --- a/js/navigation.js +++ b/js/navigation.js @@ -199,9 +199,9 @@ $(document).ready(function(){ /* Jump to recent table */ $('#recentTable').change(function() { if (this.value != '') { - var arr = this.value.split('.'); - window.parent.setDb(arr[0]); - window.parent.setTable(arr[1]); + var arr = jQuery.parseJSON(this.value); + window.parent.setDb(arr['db']); + window.parent.setTable(arr['table']); window.parent.refreshMain($('#LeftDefaultTabTable')[0].value); } }); diff --git a/libraries/RecentTable.class.php b/libraries/RecentTable.class.php index bfb60818fa..def9c37c03 100644 --- a/libraries/RecentTable.class.php +++ b/libraries/RecentTable.class.php @@ -82,7 +82,7 @@ class PMA_RecentTable $row = PMA_DBI_fetch_array(PMA_query_as_controluser($sql_query)); if (isset($row[0])) { - return json_decode($row[0]); + return json_decode($row[0], true); } else { return array(); } @@ -142,7 +142,8 @@ class PMA_RecentTable $html = ''; if (count($this->tables)) { foreach ($this->tables as $table) { - $html .= ''; + $html .= ''; } } else { $html .= ''; @@ -159,7 +160,7 @@ class PMA_RecentTable { $html = ''; - $html .= ''; $html .= $this->getHtmlSelectOption(); $html .= ''; @@ -176,12 +177,14 @@ class PMA_RecentTable */ public function add($db, $table) { - $table_str = $db . '.' . $table; + $table_arr = array(); + $table_arr['db'] = $db; + $table_arr['table'] = $table; // add only if this is new table - if (! isset($this->tables[0]) || $this->tables[0] != $table_str) { - array_unshift($this->tables, $table_str); - $this->tables = array_merge(array_unique($this->tables)); + if (! isset($this->tables[0]) || $this->tables[0] != $table_arr) { + array_unshift($this->tables, $table_arr); + $this->tables = array_merge(array_unique($this->tables, SORT_REGULAR)); $this->trim(); if (isset($this->pma_table)) { return $this->saveToDb(); diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 2b2cf60a9f..beb7f7b6c7 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -510,21 +510,22 @@ if (PMA_isValid($_REQUEST['db'])) { */ $GLOBALS['table'] = ''; if (PMA_isValid($_REQUEST['table'])) { - // check if specified table contain db name - if (strpos($_REQUEST['table'], '.')) { - $splitted = explode('.', $_REQUEST['table']); - if (count($splitted) == 2) { // make sure the format is "db.table" - $GLOBALS['db'] = $splitted[0]; - $GLOBALS['url_params']['db'] = $GLOBALS['db']; - $GLOBALS['table'] = $splitted[1]; - $GLOBALS['url_params']['table'] = $GLOBALS['table']; - } - } else { - // can we strip tags from this? - // only \ and / is not allowed in table names for MySQL - $GLOBALS['table'] = $_REQUEST['table']; - $GLOBALS['url_params']['table'] = $GLOBALS['table']; - } + // can we strip tags from this? + // only \ and / is not allowed in table names for MySQL + $GLOBALS['table'] = $_REQUEST['table']; + $GLOBALS['url_params']['table'] = $GLOBALS['table']; +} + +/** + * Store currently selected recent table. + * Affect $GLOBALS['db'] and $GLOBALS['table'] + */ +if (PMA_isValid($_REQUEST['selected_recent_table'])) { + $recent_table = json_decode($_REQUEST['selected_recent_table'], true); + $GLOBALS['db'] = $recent_table['db']; + $GLOBALS['url_params']['db'] = $GLOBALS['db']; + $GLOBALS['table'] = $recent_table['table']; + $GLOBALS['url_params']['table'] = $GLOBALS['table']; } /** From 9adfe5b99c1669cc90f70cda8acac3411686bd7f Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Fri, 5 Aug 2011 09:56:23 +0800 Subject: [PATCH 48/57] Grid edit: change the default cfg['SaveCellsAtOnce'] to false --- libraries/config.default.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/config.default.php b/libraries/config.default.php index cb0df48669..78a2fb02a6 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -2315,7 +2315,7 @@ $cfg['ShowPropertyComments']= true; /** * save edited cell(s) in browse-mode at once. */ -$cfg['SaveCellsAtOnce'] = true; +$cfg['SaveCellsAtOnce'] = false; /** * shows table display direction. From ce7909e3317acb81fde75f79e2910d8ae5bc3aef Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Sat, 6 Aug 2011 01:23:33 +0800 Subject: [PATCH 49/57] use PMA_urldecode --- js/makegrid.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/makegrid.js b/js/makegrid.js index 8b9e46e19b..7fdbf31595 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -883,7 +883,7 @@ $('.to_be_saved').parents('tr').each(function() { var $tr = $(this); var where_clause = $tr.find('.where_clause').val(); - full_where_clause.push(unescape(where_clause.replace(/[+]/g, ' '))); + full_where_clause.push(PMA_urldecode(where_clause)); var condition_array = jQuery.parseJSON($tr.find('.condition_array').val()); /** From a0391ec15a0612865e7ea04d0d7e85d2c40ec63a Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 8 Aug 2011 10:26:55 +0800 Subject: [PATCH 50/57] Fix bug - cursor permanently changed to arrow after reordering or resizing column --- js/makegrid.js | 1 - 1 file changed, 1 deletion(-) diff --git a/js/makegrid.js b/js/makegrid.js index d235f08d56..8deca29173 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -170,7 +170,6 @@ this.colMov = false; } - $('body').css('cursor', 'default'); $('body').noSelect(false); }, From 7a20d6d4df54ab7774bef43ae3ed901ca5d00fe0 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 8 Aug 2011 13:05:56 +0800 Subject: [PATCH 51/57] Grid edit: turn off grid edit when AJAXEnable = off --- js/makegrid.js | 111 ++++++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 52 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 7fdbf31595..e4d4d59474 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1167,6 +1167,62 @@ g.hideEditCell(true); } } + }, + + // initialize grid editing feature + initGridEdit: function() { + $(t).find('td.data') + .click(function(e) { + if (g.isCellEditActive) { + g.saveOrPostEditedCell(); + e.stopPropagation(); + } else { + g.showEditCell(this); + e.stopPropagation(); + } + // prevent default action when clicking on "link" in a table + if ($(e.target).is('a')) { + e.preventDefault(); + } + }); + $(g.cEdit).find('input[type=text]').focus(function(e) { + g.showEditArea(); + }); + $(g.cEdit).find('input[type=text], select').live('keydown', function(e) { + if (e.which == 13) { + // post on pressing "Enter" + e.preventDefault(); + g.saveOrPostEditedCell(); + } + }); + $(g.cEdit).keydown(function(e) { + if (!g.isEditCellTextEditable) { + // prevent text editing + e.preventDefault(); + } + }); + $('html').click(function(e) { + // hide edit cell if the click is not from g.cEdit + if ($(e.target).parents().index(g.cEdit) == -1) { + g.hideEditCell(); + } + }); + $('html').keydown(function(e) { + if (e.which == 27 && g.isCellEditActive) { + + // cancel on pressing "Esc" + g.hideEditCell(true); + } + }); + $('.save_edited').click(function() { + g.hideEditCell(); + g.postEditedCell(); + }); + $(window).bind('beforeunload', function(e) { + if (g.isCellEdited) { + return g.saveCellWarning; + } + }); } } @@ -1413,58 +1469,9 @@ g.hideColList(); }); // edit cell event - $(t).find('td.data') - .click(function(e) { - if (g.isCellEditActive) { - g.saveOrPostEditedCell(); - e.stopPropagation(); - } else { - g.showEditCell(this); - e.stopPropagation(); - } - // prevent default action when clicking on "link" in a table - if ($(e.target).is('a')) { - e.preventDefault(); - } - }); - $(g.cEdit).find('input[type=text]').focus(function(e) { - g.showEditArea(); - }); - $(g.cEdit).find('input[type=text], select').live('keydown', function(e) { - if (e.which == 13) { - // post on pressing "Enter" - e.preventDefault(); - g.saveOrPostEditedCell(); - } - }); - $(g.cEdit).keydown(function(e) { - if (!g.isEditCellTextEditable) { - // prevent text editing - e.preventDefault(); - } - }); - $('html').click(function(e) { - // hide edit cell if the click is not from g.cEdit - if ($(e.target).parents().index(g.cEdit) == -1) { - g.hideEditCell(); - } - }); - $('html').keydown(function(e) { - if (e.which == 27 && g.isCellEditActive) { - - // cancel on pressing "Esc" - g.hideEditCell(true); - } - }); - $('.save_edited').click(function() { - g.hideEditCell(); - g.postEditedCell(); - }); - $(window).bind('beforeunload', function(e) { - if (g.isCellEdited) { - g.saveCellWarning; - } - }); + if ($(t).is('.ajax')) { + g.initGridEdit(); + } // add table class $(t).addClass('pma_table'); From ba7913a2607b73008115ec71e5b14ad09cfb4d3a Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 8 Aug 2011 14:07:59 +0800 Subject: [PATCH 52/57] Remove inline edit feature --- Documentation.html | 2 +- js/db_search.js | 1 - js/makegrid.js | 6 +- js/messages.php | 1 - js/sql.js | 707 +----------------------------- js/tbl_select.js | 1 - libraries/common.inc.php | 10 +- libraries/config.default.php | 2 +- libraries/config/messages.inc.php | 2 +- libraries/display_tbl.lib.php | 24 +- sql.php | 10 +- 11 files changed, 31 insertions(+), 735 deletions(-) diff --git a/Documentation.html b/Documentation.html index 495af5110b..baa98bb9e0 100644 --- a/Documentation.html +++ b/Documentation.html @@ -1961,7 +1961,7 @@ $cfg['TrustedProxies'] =
$cfg['RowActionLinks'] string
-
Defines the place where table row links (Edit, Inline edit, Copy, +
Defines the place where table row links (Edit, Copy, Delete) would be put when tables contents are displayed (you may have them displayed at the left side, right side, both sides or nowhere). "left" and "right" are parsed as "top" diff --git a/js/db_search.js b/js/db_search.js index 72b30463d4..86a4c70567 100644 --- a/js/db_search.js +++ b/js/db_search.js @@ -31,7 +31,6 @@ function loadResult(result_path , table_name , link , ajaxEnable){ // we assign it manually from #table-link window.parent.table = $('#table-link').text().trim(); - appendInlineAnchor(); $('#table_results').makegrid(); }).show(); } diff --git a/js/makegrid.js b/js/makegrid.js index e4d4d59474..9d0529f519 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -468,7 +468,7 @@ * Show edit cell, if it can be shown or it is forced. */ showEditCell: function(cell, force) { - if ($(cell).is('.inline_edit') && + if ($(cell).is('.grid_edit') && !g.colRsz && !g.colMov) { if (!g.isCellEditActive || force) { @@ -790,7 +790,7 @@ 'db' : g.db, 'ajax_request' : true, 'sql_query' : sql_query, - 'inline_edit' : true + 'grid_edit' : true }, function(data) { $editArea.removeClass('edit_area_loading'); if(data.success == true) { @@ -871,7 +871,7 @@ /** * @var is_unique Boolean, whether the rows in this table is unique or not */ - var is_unique = $('.inline_edit_anchor').is('.nonunique') ? 0 : 1; + var is_unique = $('.edit_row_anchor').is('.nonunique') ? 0 : 1; /** * multi edit variables */ diff --git a/js/messages.php b/js/messages.php index 17d0fad6c6..bc23887628 100644 --- a/js/messages.php +++ b/js/messages.php @@ -199,7 +199,6 @@ $js_messages['strImportCSV'] = __('Note: If the file contains multiple tables, t /* For sql.js */ $js_messages['strHideQueryBox'] = __('Hide query box'); $js_messages['strShowQueryBox'] = __('Show query box'); -$js_messages['strInlineEdit'] = __('Inline Edit'); $js_messages['strEdit'] = __('Edit'); $js_messages['strSave'] = __('Save'); $js_messages['strHide'] = __('Hide'); diff --git a/js/sql.js b/js/sql.js index 1fa27cb18e..da36566b82 100644 --- a/js/sql.js +++ b/js/sql.js @@ -25,7 +25,7 @@ function PMA_urlencode(str) { /** * Get the field name for the current field. Required to construct the query - * for inline editing + * for grid editing * * @param $this_field jQuery object that points to the current field's tr */ @@ -48,68 +48,6 @@ function getFieldName($this_field) { return field_name; } -/** - * The function that iterates over each row in the table_results and appends a - * new inline edit anchor to each table row. - * - */ -function appendInlineAnchor() { - // TODO: remove two lines below if vertical display mode has been completely removed - var disp_mode = $("#top_direction_dropdown").val(); - - if (disp_mode != 'vertical') { - $('.edit_row_anchor').each(function() { - - var $this_td = $(this); - $this_td.removeClass('edit_row_anchor'); - - var $cloned_anchor = $this_td.clone(); - - var $img_object = $cloned_anchor.find('img').attr('title', PMA_messages['strInlineEdit']); - if ($img_object.length != 0) { - $img_object.removeClass('ic_b_edit'); - $img_object.addClass('ic_b_inline_edit'); - - $cloned_anchor.find('a').attr('href', '#'); - var $edit_span = $cloned_anchor.find('span:contains("' + PMA_messages['strEdit'] + '")'); - var $span = $cloned_anchor.find('a').find('span'); - if ($edit_span.length > 0) { - $span.text(' ' + PMA_messages['strInlineEdit']); - $span.prepend($img_object); - } else { - $span.text(''); - $span.append($img_object); - } - } else { - // Only text is displayed. See $cfg['PropertiesIconic'] - $cloned_anchor.find('a').attr('href', '#'); - $cloned_anchor.find('a span').text(PMA_messages['strInlineEdit']); - - // the link was too big so is there - $img_object = $cloned_anchor.find('input:image').attr('title', PMA_messages['strInlineEdit']); - if ($img_object.length > 0) { - $img_object.removeClass('ic_b_edit'); - $img_object.addClass('ic_b_inline_edit'); - } - $cloned_anchor - .find('.clickprevimage') - .text(' ' + PMA_messages['strInlineEdit']); - } - - $cloned_anchor - .addClass('inline_edit_anchor'); - - $this_td.after($cloned_anchor); - }); - - $('#resultsForm').find('thead, tbody').find('th').each(function() { - var $this_th = $(this); - if ($this_th.attr('colspan') == 4) { - $this_th.attr('colspan', '5'); - } - }); - } -} /**#@+ * @namespace jQuery @@ -124,7 +62,7 @@ function appendInlineAnchor() { *
  • Paginate the results table
  • *
  • Sort the results table
  • *
  • Change table according to display options
  • - *
  • Inline editing of data
  • + *
  • Grid editing of data
  • * * * @name document.ready @@ -147,15 +85,6 @@ $(document).ready(function() { .toggle($(this).attr('value').length > 0); }).trigger('keyup'); - /** - * Attach the {@link appendInlineAnchor} function to a custom event, which - * will be triggered manually everytime the table of results is reloaded - * @memberOf jQuery - */ - $("#sqlqueryresults").live('appendAnchor',function() { - appendInlineAnchor(); - }) - /** * Attach the {@link makegrid} function to a custom event, which will be * triggered manually everytime the table of results is reloaded @@ -167,21 +96,13 @@ $(document).ready(function() { /** * Attach the {@link refreshgrid} function to a custom event, which will be - * triggered manually everytime the table of results is manipulated (e.g., by inline edit) + * triggered manually everytime the table of results is manipulated * @memberOf jQuery */ $("#sqlqueryresults").live('refreshgrid', function() { $('#table_results').refreshgrid(); }) - /** - * Trigger the appendAnchor event to prepare the first table for inline edit - * (see $GLOBALS['cfg']['AjaxEnable']) - * @memberOf jQuery - * @name sqlqueryresults_trigger - */ - $("#sqlqueryresults.ajax").trigger('appendAnchor'); - /** * Append the "Show/Hide query box" message to the query input form * @@ -287,7 +208,6 @@ $(document).ready(function() { $sqlqueryresults .show() .html(data) - .trigger('appendAnchor') .trigger('makegrid'); $('#togglequerybox').show(); if ($("#togglequerybox").siblings(":visible").length > 0) { @@ -329,7 +249,6 @@ $(document).ready(function() { $.post($form.attr('action'), $form.serialize(), function(data) { $("#sqlqueryresults") .html(data) - .trigger('appendAnchor') .trigger('makegrid'); PMA_init_slider(); @@ -354,7 +273,6 @@ $(document).ready(function() { $.post($form.attr('action'), $form.serialize() + '&ajax_request=true', function(data) { $("#sqlqueryresults") .html(data) - .trigger('appendAnchor') .trigger('makegrid'); PMA_init_slider(); PMA_ajaxRemoveMessage($msgbox); @@ -381,7 +299,6 @@ $(document).ready(function() { $.get($anchor.attr('href'), $anchor.serialize() + '&ajax_request=true', function(data) { $("#sqlqueryresults") .html(data) - .trigger('appendAnchor') .trigger('makegrid'); PMA_ajaxRemoveMessage($msgbox); }) // end $.get() @@ -401,535 +318,12 @@ $(document).ready(function() { $.post($form.attr('action'), $form.serialize() + '&ajax_request=true' , function(data) { $("#sqlqueryresults") .html(data) - .trigger('appendAnchor') .trigger('makegrid'); PMA_init_slider(); }) // end $.post() }) //end displayOptionsForm handler - /** - * Ajax Event handlers for Inline Editing - */ - - /** - * On click, replace the fields of current row with an input/textarea - * @memberOf jQuery - * @name inline_edit_start - * @see PMA_ajaxShowMessage() - * @see getFieldName() - */ - $(".inline_edit_anchor span a").live('click', function(event) { - /** @lends jQuery */ - event.preventDefault(); - - var $edit_td = $(this).parents('td'); - $edit_td.removeClass('inline_edit_anchor').addClass('inline_edit_active').parent('tr').addClass('noclick'); - - // Adding submit and hide buttons to inline edit . - // For "hide" button the original data to be restored is - // kept in the jQuery data element 'original_data' inside the . - // Looping through all columns or rows, to find the required data and then storing it in an array. - - var $this_children = $edit_td.children('span.nowrap').children('a').children('span.nowrap'); - // Keep the original data preserved. - $data_a = $edit_td.children('span.nowrap').children('a').clone(); - - // Change the inline edit to save. - var $img_object = $this_children.find('img'); - - // If texts are displayed. See $cfg['PropertiesIconic'] - if ($this_children.parent('a').find('span:contains("' + PMA_messages['strInlineEdit'] + '")').length > 0) { - $this_children.text(' ' + PMA_messages['strSave']); - } else { - $this_children.empty(); - } - - // If icons are displayed. See $cfg['PropertiesIconic'] - if ($img_object.length > 0) { - $img_object.attr('title', PMA_messages['strSave']); - $img_object.removeClass('ic_b_inline_edit'); - $img_object.addClass('ic_b_save'); - $this_children.prepend($img_object); - } - - // Clone the save link and change it to create the hide link. - var $hide_a = $edit_td.children('span.nowrap').children('a').clone().attr('id', 'hide'); - var $hide_span = $hide_a.find('span'); - var $img_object = $hide_a.find('span img'); - - // If texts are displayed. See $cfg['PropertiesIconic'] - if ($hide_a.find('span:contains("' + PMA_messages['strSave'] + '")').length > 0) { - $hide_span.text(' ' + PMA_messages['strHide']); - } else { - $hide_span.empty(); - } - - // If icons are displayed. See $cfg['PropertiesIconic'] - if ($img_object.length > 0) { - $img_object.attr('title', PMA_messages['strHide']); - $img_object.removeClass('ic_b_save'); - $img_object.addClass('ic_b_close'); - $hide_span.prepend($img_object); - } - - // Add hide icon and/or text. - $edit_td.children('span.nowrap').append($('

    ')).append($hide_a); - - $('#table_results tbody tr td span a#hide').click(function() { - var $this_hide = $(this).parents('td'); - - var $this_span = $this_hide.find('span'); - $this_span.find('a, br').remove(); - $this_span.append($data_a.clone()); - - $this_hide.removeClass("inline_edit_active hover").addClass("inline_edit_anchor"); - $this_hide.parent().removeClass("hover noclick"); - $this_hide.siblings().removeClass("hover"); - - var $input_siblings = $this_hide.parent('tr').find('.inline_edit'); - var txt = ''; - $input_siblings.each(function() { - var $this_hide_siblings = $(this); - txt = $this_hide_siblings.data('original_data'); - if($this_hide_siblings.children('span').children().length != 0) { - $this_hide_siblings.children('span').empty(); - $this_hide_siblings.children('span').append(txt); - } - }); - $(this).prev().prev().remove(); - $(this).prev().remove(); - $(this).remove(); - - // refresh the grid - $("#sqlqueryresults").trigger('refreshgrid'); - }); - - // Initialize some variables - var this_row_index = $edit_td.parent().index(); - var $input_siblings = $edit_td.parent('tr').find('.inline_edit'); - var where_clause = $edit_td.parent('tr').find('.where_clause').val(); - - $input_siblings.each(function() { - /** @lends jQuery */ - /** - * @var data_value Current value of this field - */ - var data_value = $(this).children('span').html(); - - // We need to retrieve the value from the server for truncated/relation fields - // Find the field name - - /** - * @var this_field Object referring to this field () - */ - var $this_field = $(this); - /** - * @var this_field_span Object referring to this field's child () - */ - var $this_field_span = $(this).children('span'); - /** - * @var field_name String containing the name of this field. - * @see getFieldName() - */ - var field_name = getFieldName($this_field); - /** - * @var relation_curr_value String current value of the field (for fields that are foreign keyed). - */ - var relation_curr_value = $this_field.find('a').text(); - /** - * @var relation_key_or_display_column String relational key if in 'Relational display column' mode, - * relational display column if in 'Relational key' mode (for fields that are foreign keyed). - */ - var relation_key_or_display_column = $this_field.find('a').attr('title'); - /** - * @var curr_value String current value of the field (for fields that are of type enum or set). - */ - var curr_value = $this_field_span.text(); - - if($this_field.is(':not(.not_null)')){ - // add a checkbox to mark null for all the field that are nullable. - $this_field_span.html('
    Null :
    '); - // check the 'checkbox_null__' if the corresponding value is null - if($this_field.is('.null')) { - $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', true); - } - - // if the select/editor is changed un-check the 'checkbox_null__'. - if ($this_field.is('.enum, .set')) { - $this_field.find('select').live('change', function(e) { - $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false); - }) - } else if ($this_field.is('.relation')) { - $this_field.find('select').live('change', function(e) { - $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false); - }) - $this_field.find('.browse_foreign').live('click', function(e) { - $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false); - }) - } else { - $this_field.find('textarea').live('keypress', function(e) { - // FF errorneously triggers for modifier keys such as tab (bug #3357837) - if (e.which != 0) { - $('.checkbox_null_' + field_name + '_' + this_row_index).attr('checked', false); - } - }) - } - - // if 'checkbox_null__' is clicked empty the corresponding select/editor. - $('.checkbox_null_' + field_name + '_' + this_row_index).bind('click', function(e) { - if ($this_field.is('.enum')) { - $this_field.find('select').attr('value', ''); - } else if ($this_field.is('.set')) { - $this_field.find('select').find('option').each(function() { - var $option = $(this); - $option.attr('selected', false); - }) - } else if ($this_field.is('.relation')) { - // if the dropdown is there to select the foreign value - if ($this_field.find('select').length > 0) { - $this_field.find('select').attr('value', ''); - // if foriegn value is selected by browsing foreing values - } else { - $this_field.find('span.curr_value').empty(); - } - } else { - $this_field.find('textarea').val(''); - } - }) - - } else { - $this_field_span.html('
    '); - } - - // In each input sibling, wrap the current value in a textarea - // and store the current value in a hidden span - if($this_field.is(':not(.truncated, .transformed, .relation, .enum, .set, .null)')) { - // handle non-truncated, non-transformed, non-relation values - - value = data_value.replace("
    ", "\n"); - // We don't need to get any more data, just wrap the value - $this_field_span.append(''); - $this_field.data('original_data', data_value); - } - else if($this_field.is('.truncated, .transformed')) { - /** @lends jQuery */ - //handle truncated/transformed values values - - /** - * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data - */ - var sql_query = 'SELECT `' + field_name + '` FROM `' + window.parent.table + '` WHERE ' + PMA_urldecode(where_clause); - - // Make the Ajax call and get the data, wrap it and insert it - $.post('sql.php', { - 'token' : window.parent.token, - 'db' : window.parent.db, - 'ajax_request' : true, - 'sql_query' : sql_query, - 'inline_edit' : true - }, function(data) { - if(data.success == true) { - $this_field_span.append(''); - $this_field.data('original_data', data_value); - $("#sqlqueryresults").trigger('refreshgrid'); - } - else { - PMA_ajaxShowMessage(data.error); - } - }) // end $.post() - } - else if($this_field.is('.relation')) { - /** @lends jQuery */ - //handle relations - - /** - * @var post_params Object containing parameters for the POST request - */ - var post_params = { - 'ajax_request' : true, - 'get_relational_values' : true, - 'db' : window.parent.db, - 'table' : window.parent.table, - 'column' : field_name, - 'token' : window.parent.token, - 'curr_value' : relation_curr_value, - 'relation_key_or_display_column' : relation_key_or_display_column - } - - $.post('sql.php', post_params, function(data) { - $this_field_span.append(data.dropdown); - $this_field.data('original_data', data_value); - $("#sqlqueryresults").trigger('refreshgrid'); - }) // end $.post() - } - else if($this_field.is('.enum')) { - /** @lends jQuery */ - //handle enum fields - - /** - * @var post_params Object containing parameters for the POST request - */ - var post_params = { - 'ajax_request' : true, - 'get_enum_values' : true, - 'db' : window.parent.db, - 'table' : window.parent.table, - 'column' : field_name, - 'token' : window.parent.token, - 'curr_value' : curr_value - } - $.post('sql.php', post_params, function(data) { - $this_field_span.append(data.dropdown); - $this_field.data('original_data', data_value); - $("#sqlqueryresults").trigger('refreshgrid'); - }) // end $.post() - } - else if($this_field.is('.set')) { - /** @lends jQuery */ - //handle set fields - - /** - * @var post_params Object containing parameters for the POST request - */ - var post_params = { - 'ajax_request' : true, - 'get_set_values' : true, - 'db' : window.parent.db, - 'table' : window.parent.table, - 'column' : field_name, - 'token' : window.parent.token, - 'curr_value' : curr_value - } - - $.post('sql.php', post_params, function(data) { - $this_field_span.append(data.select); - $this_field.data('original_data', data_value); - $("#sqlqueryresults").trigger('refreshgrid'); - }) // end $.post() - } - else if($this_field.is('.null')) { - //handle null fields - $this_field_span.append(''); - $this_field.data('original_data', 'NULL'); - } - }); - - // refresh the grid - $("#sqlqueryresults").trigger('refreshgrid'); - - }) // End On click, replace the current field with an input/textarea - - /** - * After editing, clicking again should post data - * - * @memberOf jQuery - * @name inline_edit_save - * @see PMA_ajaxShowMessage() - * @see getFieldName() - */ - $(".inline_edit_active span a").live('click', function(event) { - /** @lends jQuery */ - - event.preventDefault(); - - /** - * @var $this_td Object referring to the td containing the - * "Inline Edit" link that was clicked to save the row that is - * being edited - * - */ - var $this_td = $(this).parents('td'); - var $test_element = ''; // to test the presence of a element - - // Initialize variables - var $input_siblings = $this_td.parent('tr').find('.inline_edit'); - var where_clause = $this_td.parent('tr').find('.where_clause').val(); - - /** - * @var nonunique Boolean, whether this row is unique or not - */ - if($this_td.is('.nonunique')) { - var nonunique = 0; - } - else { - var nonunique = 1; - } - - // Collect values of all fields to submit, we don't know which changed - /** - * @var relation_fields Array containing the name/value pairs of relational fields - */ - var relation_fields = {}; - /** - * @var relational_display string 'K' if relational key, 'D' if relational display column - */ - var relational_display = $("#relational_display_K").attr('checked') ? 'K' : 'D'; - /** - * @var transform_fields Array containing the name/value pairs for transformed fields - */ - var transform_fields = {}; - /** - * @var transformation_fields Boolean, if there are any transformed fields in this row - */ - var transformation_fields = false; - - /** - * @var sql_query String containing the SQL query to update this row - */ - var sql_query = 'UPDATE `' + window.parent.table + '` SET '; - - var need_to_post = false; - - var new_clause = ''; - var prev_index = -1; - - $input_siblings.each(function() { - /** @lends jQuery */ - /** - * @var this_field Object referring to this field () - */ - var $this_field = $(this); - - /** - * @var field_name String containing the name of this field. - * @see getFieldName() - */ - var field_name = getFieldName($this_field); - - /** - * @var this_field_params Array temporary storage for the name/value of current field - */ - var this_field_params = {}; - - if($this_field.is('.transformed')) { - transformation_fields = true; - } - /** - * @var is_null String capturing whether 'checkbox_null__' is checked. - */ - var is_null = $this_field.find('input:checkbox').is(':checked'); - var value; - var addQuotes = true; - - if (is_null) { - sql_query += ' `' + field_name + "`=NULL , "; - need_to_post = true; - } else { - if($this_field.is(":not(.relation, .enum, .set, .bit)")) { - this_field_params[field_name] = $this_field.find('textarea').val(); - if($this_field.is('.transformed')) { - $.extend(transform_fields, this_field_params); - } - } else if ($this_field.is('.bit')) { - this_field_params[field_name] = '0b' + $this_field.find('textarea').val(); - addQuotes = false; - } else if ($this_field.is('.set')) { - $test_element = $this_field.find('select'); - this_field_params[field_name] = $test_element.map(function(){ - return $(this).val(); - }).get().join(","); - } else { - // results from a drop-down - $test_element = $this_field.find('select'); - if ($test_element.length != 0) { - this_field_params[field_name] = $test_element.val(); - } - - // results from Browse foreign value - $test_element = $this_field.find('span.curr_value'); - if ($test_element.length != 0) { - this_field_params[field_name] = $test_element.text(); - } - - if($this_field.is('.relation')) { - $.extend(relation_fields, this_field_params); - } - } - if(where_clause.indexOf(field_name) > prev_index){ - new_clause += '`' + window.parent.table + '`.' + '`' + field_name + "` = '" + this_field_params[field_name].replace(/'/g,"''") + "'" + ' AND '; - } - if (this_field_params[field_name] != $this_field.data('original_data')) { - if (addQuotes == true) { - sql_query += ' `' + field_name + "`='" + this_field_params[field_name].replace(/'/g, "''") + "', "; - } else { - sql_query += ' `' + field_name + "`=" + this_field_params[field_name].replace(/'/g, "''") + ", "; - } - need_to_post = true; - } - } - }) - - /* - * update the where_clause, remove the last appended ' AND ' - * */ - - //Remove the last ',' appended in the above loop - sql_query = sql_query.replace(/,\s$/, ''); - //Fix non-escaped backslashes - sql_query = sql_query.replace(/\\/g, '\\\\'); - new_clause = new_clause.substring(0, new_clause.length-5); - new_clause = PMA_urlencode(new_clause); - sql_query += ' WHERE ' + PMA_urldecode(where_clause); - // Avoid updating more than one row in case there is no primary key - // (happened only for duplicate rows) - sql_query += ' LIMIT 1'; - /** - * @var rel_fields_list String, url encoded representation of {@link relations_fields} - */ - var rel_fields_list = $.param(relation_fields); - - /** - * @var transform_fields_list String, url encoded representation of {@link transform_fields} - */ - var transform_fields_list = $.param(transform_fields); - - // if inline_edit is successful, we need to go back to default view - var $del_hide = $(this).parent(); - var $chg_submit = $(this); - - if (need_to_post) { - // Make the Ajax post after setting all parameters - /** - * @var post_params Object containing parameters for the POST request - */ - var post_params = {'ajax_request' : true, - 'sql_query' : sql_query, - 'token' : window.parent.token, - 'db' : window.parent.db, - 'table' : window.parent.table, - 'clause_is_unique' : nonunique, - 'where_clause' : where_clause, - 'rel_fields_list' : rel_fields_list, - 'do_transformations' : transformation_fields, - 'transform_fields_list' : transform_fields_list, - 'relational_display' : relational_display, - 'goto' : 'sql.php', - 'submit_type' : 'save' - }; - - $.post('tbl_replace.php', post_params, function(data) { - if(data.success == true) { - PMA_ajaxShowMessage(data.message); - $this_td.parent('tr').find('.where_clause').attr('value', new_clause); - // remove possible previous feedback message - $('#result_query').remove(); - if (typeof data.sql_query != 'undefined') { - // display feedback - $('#sqlqueryresults').prepend(data.sql_query); - } - PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data); - } else { - PMA_ajaxShowMessage(data.error); - }; - }) // end $.post() - } else { - // no posting was done but still need to display the row - // in its previous format - PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, ''); - } - }) // End After editing, clicking again should post data - /** * Ajax Event for table row change * */ @@ -1085,101 +479,6 @@ $(document).ready(function() { }, 'top.frame_content') // end $(document).ready() -/** - * Visually put back the row in the state it was before entering Inline edit - * - * (when called in the situation where no posting was done, the data - * parameter is empty) - */ -function PMA_unInlineEditRow($del_hide, $chg_submit, $this_td, $input_siblings, data) { - - // deleting the hide button. remove

    tags - $del_hide.find('a, br').remove(); - // append inline edit button. - $del_hide.append($data_a.clone()); - - // changing inline_edit_active to inline_edit_anchor - $this_td.removeClass('inline_edit_active').addClass('inline_edit_anchor'); - - // removing hover, marked and noclick classes - $this_td.parent('tr').removeClass('noclick'); - $this_td.parent('tr').removeClass('hover').find('td').removeClass('hover'); - - $input_siblings.each(function() { - // Inline edit post has been successful. - $this_sibling = $(this); - $this_sibling_span = $(this).children('span'); - - var is_null = $this_sibling.find('input:checkbox').is(':checked'); - if (is_null) { - $this_sibling_span.html('NULL'); - $this_sibling.addClass('null'); - } else { - $this_sibling.removeClass('null'); - if($this_sibling.is(':not(.relation, .enum, .set)')) { - /** - * @var new_html String containing value of the data field after edit - */ - var new_html = $this_sibling.find('textarea').val(); - - if($this_sibling.is('.transformed')) { - var field_name = getFieldName($this_sibling); - if (typeof data.transformations != 'undefined') { - $.each(data.transformations, function(key, value) { - if(key == field_name) { - if($this_sibling.is('.text_plain, .application_octetstream')) { - new_html = value; - return false; - } else { - var new_value = $this_sibling.find('textarea').val(); - new_html = $(value).append(new_value); - return false; - } - } - }) - } - } - } else { - var new_html = ''; - var new_value = ''; - $test_element = $this_sibling.find('select'); - if ($test_element.length != 0) { - new_value = $test_element.val(); - } - $test_element = $this_sibling.find('span.curr_value'); - if ($test_element.length != 0) { - new_value = $test_element.text(); - } - - if($this_sibling.is('.relation')) { - var field_name = getFieldName($this_sibling); - if (typeof data.relations != 'undefined') { - $.each(data.relations, function(key, value) { - if(key == field_name) { - new_html = $(value); - return false; - } - }) - } - } else if ($this_sibling.is('.enum')) { - new_html = new_value; - } else if ($this_sibling.is('.set')) { - if (new_value != null) { - $.each(new_value, function(key, value) { - new_html = new_html + value + ','; - }) - new_html = new_html.substring(0, new_html.length-1); - } - } - } - $this_sibling_span.html(new_html); - } - }) - - // refresh the grid - $("#sqlqueryresults").trigger('refreshgrid'); -} - /** * Starting from some th, change the class of all td under it. * If isAddClass is specified, it will be used to determine whether to add or remove the class. diff --git a/js/tbl_select.js b/js/tbl_select.js index cb0c67044f..3bc1137c5d 100644 --- a/js/tbl_select.js +++ b/js/tbl_select.js @@ -66,7 +66,6 @@ $(document).ready(function() { if (typeof response == 'string') { // found results $("#sqlqueryresults").html(response); - $("#sqlqueryresults").trigger('appendAnchor'); $("#sqlqueryresults").trigger('makegrid'); $('#tbl_search_form') // work around for bug #3168569 - Issue on toggling the "Hide search criteria" in chrome. diff --git a/libraries/common.inc.php b/libraries/common.inc.php index 53cde17982..124b090aef 100644 --- a/libraries/common.inc.php +++ b/libraries/common.inc.php @@ -1003,16 +1003,16 @@ if (isset($_REQUEST['ajax_request']) && $_REQUEST['ajax_request'] == true) { } /** - * @global boolean $GLOBALS['inline_edit'] + * @global boolean $GLOBALS['grid_edit'] * - * Set to true if this is a request made during an inline edit process. This + * Set to true if this is a request made during an grid edit process. This * request is made to retrieve the non-truncated/transformed values. */ -if (isset($_REQUEST['inline_edit']) && $_REQUEST['inline_edit'] == true) { - $GLOBALS['inline_edit'] = true; +if (isset($_REQUEST['grid_edit']) && $_REQUEST['grid_edit'] == true) { + $GLOBALS['grid_edit'] = true; } else { - $GLOBALS['inline_edit'] = false; + $GLOBALS['grid_edit'] = false; } if (!empty($__redirect) && in_array($__redirect, $goto_whitelist)) { diff --git a/libraries/config.default.php b/libraries/config.default.php index 78a2fb02a6..535e0eac3c 100644 --- a/libraries/config.default.php +++ b/libraries/config.default.php @@ -2258,7 +2258,7 @@ $cfg['CharTextareaRows'] = 2; $cfg['LimitChars'] = 50; /** - * Where to show the edit/inline_edit/delete links in browse mode + * Where to show the edit/copy/delete links in browse mode * Possible values are 'left', 'right', 'both' and 'none'; * which will be interpreted as 'top', 'bottom', 'both' and 'none' * respectively for vertical display mode diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php index 96e903ef24..0249950192 100644 --- a/libraries/config/messages.inc.php +++ b/libraries/config/messages.inc.php @@ -316,7 +316,7 @@ $strConfigMcryptDisableWarning_desc = __('Disable the default warning that is di $strConfigMcryptDisableWarning_name = __('mcrypt warning'); $strConfigMemoryLimit_desc = __('The number of bytes a script is allowed to allocate, eg. [kbd]32M[/kbd] ([kbd]0[/kbd] for no limit)'); $strConfigMemoryLimit_name = __('Memory limit'); -$strConfigRowActionLinks_desc = __('These are Edit, Inline edit, Copy and Delete links'); +$strConfigRowActionLinks_desc = __('These are Edit, Copy and Delete links'); $strConfigRowActionLinks_name = __('Where to show the table row links'); $strConfigNaturalOrder_desc = __('Use natural order for sorting table and database names'); $strConfigNaturalOrder_name = __('Natural order'); diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index fc57236269..a371add3ae 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -1095,7 +1095,7 @@ function PMA_buildValueDisplay($class, $condition_field, $value) { * @return string the td */ function PMA_buildNullDisplay($class, $condition_field) { - // the null class is needed for inline editing + // the null class is needed for grid editing return 'NULL'; } @@ -1216,8 +1216,8 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { $vertical_display['delete'] = array(); $vertical_display['data'] = array(); $vertical_display['row_delete'] = array(); - // name of the class added to all inline editable elements - $inline_edit_class = 'inline_edit'; + // name of the class added to all grid editable elements + $grid_edit_class = 'grid_edit'; // prepare to get the column order, if available if (PMA_isSelect()) { @@ -1315,7 +1315,7 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { $edit_str = PMA_getIcon('b_edit.png', __('Edit'), true); $copy_str = PMA_getIcon('b_insrow.png', __('Copy'), true); - // Class definitions required for inline editing jQuery scripts + // Class definitions required for grid editing jQuery scripts $edit_anchor_class = "edit_row_anchor"; if ( $clause_is_unique == 0) { $edit_anchor_class .= ' nonunique'; @@ -1403,8 +1403,8 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { $pointer = $i; $is_field_truncated = false; //If the previous column had blob data, we need to reset the class - // to $inline_edit_class - $class = 'data ' . $inline_edit_class . ' ' . $not_null_class . ' ' . $relation_class; //' ' . $alternating_color_class . + // to $grid_edit_class + $class = 'data ' . $grid_edit_class . ' ' . $not_null_class . ' ' . $relation_class; //' ' . $alternating_color_class . // See if this column should get highlight because it's used in the // where-query. @@ -1490,8 +1490,8 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { $field_flags = PMA_DBI_field_flags($dt_result, $i); if (stristr($field_flags, 'BINARY')) { - // remove 'inline_edit' from $class as we can't edit binary data. - $class = str_replace('inline_edit', '', $class); + // remove 'grid_edit' from $class as we can't edit binary data. + $class = str_replace('grid_edit', '', $class); if (! isset($row[$i]) || is_null($row[$i])) { $vertical_display['data'][$row_no][$i] = PMA_buildNullDisplay($class, $condition_field); @@ -1533,8 +1533,8 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { // g e o m e t r y } elseif ($meta->type == 'geometry') { - // Remove 'inline_edit' from $class as we do not allow to inline-edit geometry data. - $class = str_replace('inline_edit', '', $class); + // Remove 'grid_edit' from $class as we do not allow to inline-edit geometry data. + $class = str_replace('grid_edit', '', $class); // Display as [GEOMETRY - (size)] if ('GEOM' == $_SESSION['tmp_user_values']['geometry_display']) { @@ -2745,7 +2745,7 @@ function PMA_generateEditLink($edit_url, $class, $edit_str, $where_clause, $wher . PMA_linkOrButton($edit_url, $edit_str, array(), false); /* * Where clause for selecting this row uniquely is provided as - * a hidden input. Used by jQuery scripts for handling inline editing + * a hidden input. Used by jQuery scripts for handling grid editing */ if (! empty($where_clause)) { $ret .= ''; @@ -2775,7 +2775,7 @@ function PMA_generateCopyLink($copy_url, $copy_str, $where_clause, $where_clause . PMA_linkOrButton($copy_url, $copy_str, array(), false); /* * Where clause for selecting this row uniquely is provided as - * a hidden input. Used by jQuery scripts for handling inline editing + * a hidden input. Used by jQuery scripts for handling grid editing */ if (! empty($where_clause)) { $ret .= ''; diff --git a/sql.php b/sql.php index 94a0b0d1e5..bf9f4f8046 100644 --- a/sql.php +++ b/sql.php @@ -58,7 +58,7 @@ if (isset($fields['dbase'])) { } /** - * During inline edit, if we have a relational field, show the dropdown for it + * During grid edit, if we have a relational field, show the dropdown for it * * Logic taken from libraries/display_tbl_lib.php * @@ -104,7 +104,7 @@ if (isset($_REQUEST['get_relational_values']) && $_REQUEST['get_relational_value } /** - * Just like above, find possible values for enum fields during inline edit. + * Just like above, find possible values for enum fields during grid edit. * * Logic taken from libraries/display_tbl_lib.php */ @@ -133,7 +133,7 @@ if (isset($_REQUEST['get_enum_values']) && $_REQUEST['get_enum_values'] == true) } /** - * Find possible values for set fields during inline edit. + * Find possible values for set fields during grid edit. */ if (isset($_REQUEST['get_set_values']) && $_REQUEST['get_set_values'] == true) { $field_info_query = 'SHOW FIELDS FROM `' . $db . '`.`' . $table . '` LIKE \'' . $_REQUEST['column'] . '\' ;'; @@ -696,7 +696,7 @@ if (0 == $num_rows || $is_affected) { if ($GLOBALS['is_ajax_request'] == true) { /** - * If we are in inline editing, we need to process the relational and + * If we are in grid editing, we need to process the relational and * transformed fields, if they were edited. After that, output the correct * link/transformed value and exit * @@ -859,7 +859,7 @@ if (0 == $num_rows || $is_affected) { else { //If we are retrieving the full value of a truncated field or the original // value of a transformed field, show it here and exit - if ($GLOBALS['inline_edit'] == true && $GLOBALS['cfg']['AjaxEnable']) { + if ($GLOBALS['grid_edit'] == true && $GLOBALS['cfg']['AjaxEnable']) { $row = PMA_DBI_fetch_row($result); $extra_data = array(); $extra_data['value'] = $row[0]; From 7b3d0f0107f7fe7e15911714b3a015a8cad0350f Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 8 Aug 2011 14:34:08 +0800 Subject: [PATCH 53/57] Fix bug - show/hide feature not working correctly (maybe caused by merge error in git) --- libraries/display_tbl.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index 87ec0d7067..a27a815a41 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -1399,7 +1399,7 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { $is_field_truncated = false; //If the previous column had blob data, we need to reset the class // to $inline_edit_class - $class = 'data ' . $inline_edit_class . ' ' . $not_null_class . ' ' . $relation_class; //' ' . $alternating_color_class . + $class = 'data ' . $inline_edit_class . ' ' . $not_null_class . ' ' . $relation_class . ' ' . $hide_class; //' ' . $alternating_color_class . // See if this column should get highlight because it's used in the // where-query. From c13f3fda43049938e374cc42d47d4a166390a9d2 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Mon, 8 Aug 2011 17:14:59 +0800 Subject: [PATCH 54/57] Fix error caused on previous merge conflict --- libraries/display_tbl.lib.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index bc65fc4b3c..ff27f9e3c1 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -1399,7 +1399,7 @@ function PMA_displayTableBody(&$dt_result, &$is_display, $map, $analyzed_sql) { $is_field_truncated = false; //If the previous column had blob data, we need to reset the class // to $inline_edit_class - $class = 'data ' . $inline_edit_class . ' ' . $not_null_class . ' ' . $relation_class . ' ' . $hide_class; //' ' . $alternating_color_class . + $class = 'data ' . $grid_edit_class . ' ' . $not_null_class . ' ' . $relation_class . ' ' . $hide_class; //' ' . $alternating_color_class . // See if this column should get highlight because it's used in the // where-query. From 124b6793fb22cb6cf41682da8d6c7dc98ce74193 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Tue, 9 Aug 2011 15:06:27 +0800 Subject: [PATCH 55/57] Grid edit: nullify lastXHR after post successful --- js/makegrid.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/makegrid.js b/js/makegrid.js index 9d0529f519..7a2cd94da6 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -686,6 +686,7 @@ } g.lastXHR = $.post('sql.php', post_params, function(data) { + g.lastXHR = null; $editArea.removeClass('edit_area_loading'); // save original_data var value = $(data.dropdown).val(); @@ -720,6 +721,7 @@ 'curr_value' : curr_value } g.lastXHR = $.post('sql.php', post_params, function(data) { + g.lastXHR = null; $editArea.removeClass('edit_area_loading'); $editArea.append(data.dropdown); $editArea.append('
    ' + g.cellEditHint + '
    '); @@ -749,6 +751,7 @@ } g.lastXHR = $.post('sql.php', post_params, function(data) { + g.lastXHR = null; $editArea.removeClass('edit_area_loading'); $editArea.append(data.select); $editArea.append('
    ' + g.cellEditHint + '
    '); @@ -792,6 +795,7 @@ 'sql_query' : sql_query, 'grid_edit' : true }, function(data) { + g.lastXHR = null; $editArea.removeClass('edit_area_loading'); if(data.success == true) { if ($td.is('.truncated')) { From 0319a00d92966c49fbcb3fdfe4d9a6e45d2cc8d7 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Tue, 2 Aug 2011 10:20:41 +0800 Subject: [PATCH 56/57] Fix bug - duplicate ID in some data and text for makegrid.js --- js/makegrid.js | 14 ++++----- js/messages.php | 10 +++++++ libraries/display_tbl.lib.php | 56 ++++++++++++++--------------------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/js/makegrid.js b/js/makegrid.js index 7a2cd94da6..71ed04ca1a 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -1284,15 +1284,15 @@ g.tableCreateTime = $('#table_create_time').val(); // assign column reorder & column sort hint - g.reorderHint = $('#col_order_hint').val(); - g.sortHint = $('#sort_hint').val(); - g.markHint = $('#col_mark_hint').val(); - g.colVisibHint = $('#col_visib_hint').val(); - g.showAllColText = $('#show_all_col_text').val(); + g.reorderHint = PMA_messages['strColOrderHint']; + g.sortHint = PMA_messages['strSortHint']; + g.markHint = PMA_messages['strColMarkHint']; + g.colVisibHint = PMA_messages['strColVisibHint']; + g.showAllColText = PMA_messages['strShowAllCol']; // assign cell editing hint - g.cellEditHint = $('#cell_edit_hint').val(); - g.saveCellWarning = $('#save_cell_warning').val(); + g.cellEditHint = PMA_messages['strCellEditHint']; + g.saveCellWarning = PMA_messages['strSaveCellWarning']; // initialize cell editing configuration g.saveCellsAtOnce = $('#save_cells_at_once').val(); diff --git a/js/messages.php b/js/messages.php index bc23887628..b555b7183e 100644 --- a/js/messages.php +++ b/js/messages.php @@ -226,6 +226,15 @@ $js_messages['strLeavingDesigner'] = __('You haven\'t saved the changes in the l /* Visual query builder (pmd/scripts/move.js) */ $js_messages['strAddOption'] = __('Add an option for column '); +/* For makegrid.js (column reordering, show/hide column, grid editing) */ +$js_messages['strCellEditHint'] = __('Press escape to cancel editing'); +$js_messages['strSaveCellWarning'] = __('You have edited some data and they have not been saved. Are you sure you want to leave this page before saving the data?'); +$js_messages['strColOrderHint'] = __('Drag to reorder'); +$js_messages['strSortHint'] = __('Click to sort'); +$js_messages['strColMarkHint'] = __('Click to mark/unmark'); +$js_messages['strColVisibHint'] = __('Click the drop-down arrow
    to toggle column\'s visibility'); +$js_messages['strShowAllCol'] = __('Show all'); + /* password generation */ $js_messages['strGeneratePassword'] = __('Generate password'); $js_messages['strGenerate'] = __('Generate'); @@ -240,6 +249,7 @@ $js_messages['strNewerVersion'] = __('A newer version of phpMyAdmin is available $js_messages['strLatestAvailable'] = __(', latest stable version:'); $js_messages['strUpToDate'] = __('up to date'); + echo "var PMA_messages = new Array();\n"; foreach ($js_messages as $name => $js_message) { PMA_printJsValue("PMA_messages['" . $name . "']", $js_message); diff --git a/libraries/display_tbl.lib.php b/libraries/display_tbl.lib.php index a371add3ae..1b70d3a031 100644 --- a/libraries/display_tbl.lib.php +++ b/libraries/display_tbl.lib.php @@ -394,45 +394,12 @@ function PMA_displayTableNavigation($pos_next, $pos_prev, $sql_query, $id_for_di
    - '; ?> - '; ?> - '; ?> - '; - echo PMA_generate_common_hidden_inputs($db, $table); - echo '
    '; - ?>
    - getUiProp(PMA_Table::PROP_COLUMN_ORDER); - if ($col_order) { - echo ''; - } - $col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB); - if ($col_visib) { - echo ''; - } - // generate table create time - echo ''; - } - // generate hints - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - ?> '; + echo '
    '; + echo PMA_generate_common_hidden_inputs($db, $table); + echo '
    '; + // Output data needed for column reordering and show/hide column + if (PMA_isSelect()) { + // generate the column order, if it is set + $pmatable = new PMA_Table($GLOBALS['table'], $GLOBALS['db']); + $col_order = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_ORDER); + if ($col_order) { + echo ''; + } + $col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB); + if ($col_visib) { + echo ''; + } + // generate table create time + echo ''; + } + + $vertical_display['emptypre'] = 0; $vertical_display['emptyafter'] = 0; $vertical_display['textbtn'] = ''; From af099deba48ed34e733bba286bbbe0a3e8f24f12 Mon Sep 17 00:00:00 2001 From: Aris Feryanto Date: Tue, 9 Aug 2011 15:53:58 +0800 Subject: [PATCH 57/57] Grid edit: alert user when saving non-unique table --- js/makegrid.js | 14 ++++++++++++++ js/messages.php | 1 + 2 files changed, 15 insertions(+) diff --git a/js/makegrid.js b/js/makegrid.js index 71ed04ca1a..30892f3c78 100644 --- a/js/makegrid.js +++ b/js/makegrid.js @@ -33,6 +33,8 @@ isCellEdited: false, // true if at least one cell has been edited saveCellWarning: '', // string, warning text when user want to leave a page with unsaved edited data lastXHR : null, // last XHR object used in AJAX request + isSaving: false, // true when currently saving edited data, used to handle double posting caused by pressing ENTER in grid edit text box in Chrome browser + alertNonUnique: '', // string, alert shown when saving edited nonunique table // common hidden inputs token: null, @@ -840,6 +842,11 @@ * Post the content of edited cell. */ postEditedCell: function() { + if (g.isSaving) { + return; + } + g.isSaving = true; + /** * @var relation_fields Array containing the name/value pairs of relational fields */ @@ -883,6 +890,11 @@ var me_fields = Array(); var me_fields_null = Array(); + // alert user if edited table is not unique + if (!is_unique) { + alert(g.alertNonUnique); + } + // loop each edited row $('.to_be_saved').parents('tr').each(function() { var $tr = $(this); @@ -1017,6 +1029,7 @@ data: post_params, success: function(data) { + g.isSaving = false; if (!g.saveCellsAtOnce) { $(g.cEdit).find('*').removeAttr('disabled'); $editArea.removeClass('edit_area_posting'); @@ -1293,6 +1306,7 @@ // assign cell editing hint g.cellEditHint = PMA_messages['strCellEditHint']; g.saveCellWarning = PMA_messages['strSaveCellWarning']; + g.alertNonUnique = PMA_messages['strAlertNonUnique']; // initialize cell editing configuration g.saveCellsAtOnce = $('#save_cells_at_once').val(); diff --git a/js/messages.php b/js/messages.php index b555b7183e..2c4e90ace3 100644 --- a/js/messages.php +++ b/js/messages.php @@ -234,6 +234,7 @@ $js_messages['strSortHint'] = __('Click to sort'); $js_messages['strColMarkHint'] = __('Click to mark/unmark'); $js_messages['strColVisibHint'] = __('Click the drop-down arrow
    to toggle column\'s visibility'); $js_messages['strShowAllCol'] = __('Show all'); +$js_messages['strAlertNonUnique'] = __('This table contains no unique field. Features related to the grid edit, checkbox, Edit, Copy and Delete links may not work after saving.'); /* password generation */ $js_messages['strGeneratePassword'] = __('Generate password');