diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 0fda9145..0068c101 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -515,7 +515,7 @@ function input($field, $value, $function) { } elseif (ereg('binary|blob|bytea', $field["type"]) && ini_bool("file_uploads")) { echo ""; } elseif (ereg('text|blob', $field["type"])) { - echo "'; + echo "'; // 1.2em - line-height } else { // int(3) is only a display hint $maxlength = (!ereg('int', $field["type"]) && preg_match('~^([0-9]+)(,([0-9]+))?$~', $field["length"], $match) ? ($match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0)); diff --git a/adminer/select.inc.php b/adminer/select.inc.php index 25e710d3..8e0db84d 100644 --- a/adminer/select.inc.php +++ b/adminer/select.inc.php @@ -61,7 +61,7 @@ if ($_POST && !$error) { exit; } if (!$adminer->selectEmailProcess($where, $foreign_keys)) { - if (!$_POST["import"]) { // edit + if ($_POST["save"]) { // edit $result = true; $affected = 0; $query = idf_escape($TABLE); @@ -105,6 +105,21 @@ if ($_POST && !$error) { } queries_redirect(remove_from_uri("page"), lang('%d item(s) have been affected.', $affected), $result); //! display edit page in case of an error + } elseif (!$_POST["import"]) { // modify + $result = true; + $affected = 0; + foreach ($_POST["val"] as $unique_idf => $row) { + $set = array(); + foreach ($row as $key => $val) { + $set[] = idf_escape(bracket_escape($key, 1)) . " = " . $connection->quote($val); // 1 - back //! $adminer->editVal($val) + } + $result = queries("UPDATE " . idf_escape($TABLE) . " SET " . implode(", ", $set) . " WHERE " . where_check($unique_idf)); + if (!$result) { + break; + } + $affected += $connection->affected_rows; + } + queries_redirect(remove_from_uri(), lang('%d item(s) have been affected.', $affected), $result); } elseif (is_string($file = get_file("csv_file", true))) { $file = preg_replace("~^\xEF\xBB\xBF~", '', $file); //! character set $result = true; @@ -144,6 +159,7 @@ if ($_POST && !$error) { $table_name = $adminer->tableName($table_status); page_header(lang('Select') . ": $table_name", $error); +session_write_close(); $set = null; if (isset($rights["insert"])) { @@ -177,7 +193,6 @@ if (!$columns) { $page = $_GET["page"]; if ($page == "last") { - session_write_close(); $found_rows = $connection->result("SELECT COUNT(*) FROM " . idf_escape($TABLE) . ($where ? " WHERE " . implode(" AND ", $where) : "")); $page = floor(($found_rows - 1) / $limit); } @@ -212,7 +227,7 @@ if (!$columns) { $backward_keys = $adminer->backwardKeys($TABLE, $table_name); echo "\n"; - echo "\n"; foreach ($adminer->rowDescriptions($rows, $foreign_keys) as $n => $row) { $unique_array = unique_array($rows[$n], $indexes); @@ -239,7 +262,7 @@ if (!$columns) { if (isset($names[$key])) { $field = $fields[$key]; if ($val != "" && (!isset($email_fields[$key]) || $email_fields[$key] != "")) { - $email_fields[$key] = (is_email($val) ? $names[$key] : ""); //! filled e-mails may be contained on other pages + $email_fields[$key] = (is_email($val) ? $names[$key] : ""); //! filled e-mails can be contained on other pages } $link = ""; $val = $adminer->editVal($val, $field); @@ -285,10 +308,17 @@ if (!$columns) { $link = "mailto:$val"; } if (!$link && is_url($row[$key])) { - $link = "http://www.adminer.org/redirect/?url=" . urlencode($row[$key]); // intermediate page to hide Referer + $link = "http://www.adminer.org/redirect/?url=" . urlencode($row[$key]); // intermediate page to hide Referer, may be changed to rel="noreferrer" in HTML5 } - $val = $adminer->selectVal($val, $link, $field); - echo "
"; + echo "
" . lang('edit') . ""; $names = array(); reset($select); $order = 1; @@ -227,6 +242,14 @@ if (!$columns) { } next($select); } + $lengths = array(); + if ($_GET["modify"]) { + foreach ($rows as $row) { + foreach ($row as $key => $val) { + $lengths[$key] = max($lengths[$key], min(40, strlen(utf8_decode($val)))); + } + } + } echo ($backward_keys ? "" . lang('Relations') : "") . "
$val"; + $id = h("val[$unique_idf][" . bracket_escape($key) . "]"); + $value = $_POST["val"][$unique_idf][bracket_escape($key)]; + $h_value = h(isset($value) ? $value : $row[$key]); + $editable = is_utf8($val) && !strpos($val, "..."); + $text = ereg('text|blob', $field["type"]); + echo (($_GET["modify"] && $editable) || isset($value) + ? "" . ($text ? "" : "") + : "" . $adminer->selectVal($val, $link, $field) + ); } } $adminer->backwardKeysPrint($backward_keys, $rows[$n]); @@ -324,7 +354,16 @@ if (!$columns) { } echo " (" . ($exact_count ? "" : "~ ") . lang('%d row(s)', $found_rows) . ") " . checkbox("all", 1, 0, lang('whole result')) . "\n"; - echo (information_schema(DB) ? "" : "
" . lang('Edit') . "
\n"); + if (!information_schema(DB)) { + ?> +
+ onclick="if (!selectDblClicked) { alert(''); return false; };"> + + + +
+dumpOutput(1, $adminer_export["output"]) . " " . $adminer->dumpFormat(1, $adminer_export["format"]); // 1 - select echo " \n"; diff --git a/adminer/static/functions.js b/adminer/static/functions.js index 3ff592c3..5be20596 100644 --- a/adminer/static/functions.js +++ b/adminer/static/functions.js @@ -119,3 +119,40 @@ function selectAddRow(field) { field.parentNode.parentNode.appendChild(row); field.onchange = function () { }; } + +var selectDblClicked = false; +function selectDblClick(td, event, text) { + selectDblClicked = true; + var pos = event.rangeOffset; + var value = (td.firstChild.firstChild ? td.firstChild.firstChild.data : td.firstChild.data); + var input = document.createElement(text ? 'textarea' : 'input'); + input.name = td.id; + input.value = (value == '\u00A0' || td.getElementsByTagName('i').length ? '' : value); //   or i - NULL + input.style.width = (td.clientWidth - 14) + 'px'; // 14 = 2 * (td.border + td.padding + input.border) + if (text) { + var rows = 1; + value.replace(/\n/g, function () { + rows++; + }); + input.rows = rows; + } + if (document.selection) { + var range = document.selection.createRange(); + range.moveToPoint(event.x, event.y); + var range2 = range.duplicate(); + range2.moveToElementText(td); + range2.setEndPoint('EndToEnd', range); + pos = range2.text.length; + } + td.innerHTML = ''; + td.appendChild(input); + input.focus(); + input.selectionStart = pos; + input.selectionEnd = pos; + if (document.selection) { + var range = document.selection.createRange(); + range.moveStart('character', pos); + range.select(); + } + td.ondblclick = function () { }; +} diff --git a/changes.txt b/changes.txt index 66e66ad4..b4d87ddd 100644 --- a/changes.txt +++ b/changes.txt @@ -1,7 +1,8 @@ Adminer 3.0.0-dev: Drivers for MS SQL, SQLite, PostgreSQL -Show number of tables in server overview Allow concurrent logins on the same server +In-place editation in select +Show number of tables in server overview Operator LIKE %% Remember export parameters in cookie Allow semicolon as CSV separator diff --git a/todo.txt b/todo.txt index 4d9d5c44..9d7af527 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,5 @@ Transactions in export Create view and routine options -Mass editation of individual rows Variables editation, especially timezone Optionally check IP address Disable spell checking in SQL textareas - spellcheck="false" @@ -11,10 +10,11 @@ Add title to Logout, edit (in select) and select (in menu) in style "hever" Shift-click in checkboxes to select range Export by GET parameters Only first part of big BZ2 export is readable +Auto-refresh processlist (thanks to Jan Garaj) +Show pagination above and under the table in select ? Column and table names auto-completition in SQL textarea ? Aliasing of built-in functions can save 7 KB, function minification can save 7 KB, substitution of repetitive $a["a"] can save 4 KB, substitution of $_GET and friends can save 2 KB, aliasing of $connection->query, $connection->result and $connection->quote can save ~ 3 KB, JS packer can save 1 KB, not enclosing HTML attribute values can save 1.2 KB, replacing \\n by \n can save .3 KB ? Branch binary_compile: LZW compression of translations can save 30 KB, LZW compression of all texts can save 11 KB, remove of base64_decode() + using chars 127-255 in minification can save 1 KB -? AJAX editing - select page has all data to display edit form Editor: JavaScript data validation - columns containing word email, url, ...