1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-29 17:19:52 +02:00

Integrate tables-filter plugin into the base code

This commit is contained in:
Peter Knut
2024-10-05 23:54:55 +02:00
parent bf1d16cdb7
commit 279337aa65
6 changed files with 139 additions and 94 deletions

View File

@@ -1062,6 +1062,7 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
if (!$tables) { if (!$tables) {
echo "<p class='message'>" . lang('No tables.') . "\n"; echo "<p class='message'>" . lang('No tables.') . "\n";
} else { } else {
$this->printTablesFilter();
$this->tablesPrint($tables); $this->tablesPrint($tables);
} }
} }
@@ -1106,28 +1107,51 @@ bodyLoad('<?php echo (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '
echo "</p></form>\n"; echo "</p></form>\n";
} }
/** Prints table list in menu function printTablesFilter()
* @param array result of table_status('', true) {
* @return null global $adminer;
*/
function tablesPrint($tables) { echo "<div class='tables-filter jsonly'>"
. "<input id='tables-filter' autocomplete='off' placeholder='" . lang('Table') . "'>"
. script("initTablesFilter(" . json_encode($adminer->database()) . ");")
. "</div>\n";
}
/**
* Prints table list in menu.
*
* @param array $tables Result of table_status('', true)
* @return null
*/
function tablesPrint(array $tables) {
echo "<ul id='tables'>" . script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});"); echo "<ul id='tables'>" . script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");
foreach ($tables as $table => $status) { foreach ($tables as $table => $status) {
$name = $this->tableName($status); $name = $this->tableName($status);
if ($name != "") { if ($name != "") {
$active = $table == $_GET["select"] || $table == $_GET["edit"];
echo '<li><a href="' . h(ME) . 'select=' . urlencode($table) . '"' echo '<li><a href="' . h(ME) . 'select=' . urlencode($table) . '"'
. bold($_GET["select"] == $table || $_GET["edit"] == $table, "select") . bold($active, "select")
. " title='" . lang('Select data') . "'>" . lang('select') . "</a> " . " title='" . lang('Select data') . "'>" . lang('select') . "</a> ";
;
echo (support("table") || support("indexes") if (support("table") || support("indexes")) {
? '<a href="' . h(ME) . 'table=' . urlencode($table) . '"' $active = in_array($table, [$_GET["table"], $_GET["create"], $_GET["indexes"], $_GET["foreign"], $_GET["trigger"]]);
. bold(in_array($table, array($_GET["table"], $_GET["create"], $_GET["indexes"], $_GET["foreign"], $_GET["trigger"])), (is_view($status) ? "view" : "structure")) $class = is_view($status) ? "view" : "structure";
. " title='" . lang('Show structure') . "'>$name</a>"
: "<span>$name</span>" echo '<a href="' . h(ME) . 'table=' . urlencode($table) . '"' . bold($active, $class)
) . "\n"; . " title='" . lang('Show structure') . "' data-main='true'>$name</a>";
} else {
echo "<span data-main='true'>$name</span>";
}
echo "</li>\n";
} }
} }
echo "</ul>\n"; echo "</ul>\n";
return null;
} }
} }

View File

@@ -31,6 +31,7 @@ input.default { box-shadow: 1px 1px 1px #777; }
input.required { box-shadow: 1px 1px 1px red; } input.required { box-shadow: 1px 1px 1px red; }
input.maxlength { box-shadow: 1px 1px 1px red; } input.maxlength { box-shadow: 1px 1px 1px red; }
input.wayoff { left: -1000px; position: absolute; } input.wayoff { left: -1000px; position: absolute; }
input::placeholder { color: #000; opacity: 0.4; }
.center { text-align: center; } .center { text-align: center; }
.block { display: block; } .block { display: block; }
.version { color: #777; font-size: 67%; } .version { color: #777; font-size: 67%; }
@@ -68,6 +69,7 @@ input.wayoff { left: -1000px; position: absolute; }
.links a { white-space: nowrap; margin-right: 20px; } .links a { white-space: nowrap; margin-right: 20px; }
.logout { margin-top: .5em; position: absolute; top: 0; right: 0; } .logout { margin-top: .5em; position: absolute; top: 0; right: 0; }
.loadmore { margin-left: 1ex; } .loadmore { margin-left: 1ex; }
.tables-filter { padding: .8em 1em 0; }
/* .edit used in designs */ /* .edit used in designs */
#menu { position: absolute; margin: 10px 0 0; padding: 0 0 30px 0; top: 2em; left: 0; width: 19em; } #menu { position: absolute; margin: 10px 0 0; padding: 0 0 30px 0; top: 2em; left: 0; width: 19em; }
#menu p, #logins, #tables { padding: .8em 1em; margin: 0; border-bottom: 1px solid #ccc; } #menu p, #logins, #tables { padding: .8em 1em; margin: 0; border-bottom: 1px solid #ccc; }
@@ -83,6 +85,7 @@ input.wayoff { left: -1000px; position: absolute; }
#schema { margin-left: 60px; position: relative; -moz-user-select: none; -webkit-user-select: none; } #schema { margin-left: 60px; position: relative; -moz-user-select: none; -webkit-user-select: none; }
#schema .table { border: 1px solid silver; padding: 0 2px; cursor: move; position: absolute; } #schema .table { border: 1px solid silver; padding: 0 2px; cursor: move; position: absolute; }
#schema .references { position: absolute; } #schema .references { position: absolute; }
#tables-filter { width: 100%; }
#help { position: absolute; border: 1px solid #999; background: #eee; padding: 5px; font-family: monospace; z-index: 1; } #help { position: absolute; border: 1px solid #999; background: #eee; padding: 5px; font-family: monospace; z-index: 1; }
.rtl h2 { margin: 0 -18px 20px 0; } .rtl h2 { margin: 0 -18px 20px 0; }

View File

@@ -357,7 +357,78 @@ function pageClick(href, page) {
} }
} }
let tablesFilterTimeout = null;
let tablesFilterValue = '';
function initTablesFilter(dbName) {
if (sessionStorage) {
document.addEventListener('DOMContentLoaded', function () {
if (dbName === sessionStorage.getItem('adminer_tables_filter_db') && sessionStorage.getItem('adminer_tables_filter')) {
qs('#tables-filter').value = sessionStorage.getItem('adminer_tables_filter');
filterTables();
} else {
sessionStorage.removeItem('adminer_tables_filter');
}
sessionStorage.setItem('adminer_tables_filter_db', dbName);
});
}
const filterInput = qs('#tables-filter');
filterInput.addEventListener('input', function () {
window.clearTimeout(tablesFilterTimeout);
tablesFilterTimeout = window.setTimeout(filterTables, 200);
});
document.body.addEventListener('keydown', function(event) {
if (isCtrl(event) && event.shiftKey && event.key.toUpperCase() === 'F') {
filterInput.focus();
filterInput.select();
event.preventDefault();
}
});
}
function filterTables() {
const value = qs('#tables-filter').value.toLowerCase();
if (value === tablesFilterValue) {
return;
}
tablesFilterValue = value;
let reg
if (value !== '') {
const valueExp = (`${value}`).replace(/[\\.+*?\[^\]$(){}=!<>|:]/g, '\\$&');
reg = new RegExp(`(${valueExp})`, 'gi');
}
if (sessionStorage) {
sessionStorage.setItem('adminer_tables_filter', value);
}
const tables = qsa('#tables li');
for (let i = 0; i < tables.length; i++) {
let a = qs('a[data-main="true"], span[data-main="true"]', tables[i]);
let tableName = tables[i].dataset.tableName;
if (tableName == null) {
tableName = a.innerHTML.trim();
tables[i].dataset.tableName = tableName;
}
if (value === "") {
tables[i].classList.remove('hidden');
a.innerHTML = tableName;
} else if (tableName.toLowerCase().indexOf(value) >= 0) {
tables[i].classList.remove('hidden');
a.innerHTML = tableName.replace(reg, '<strong>$1</strong>');
} else {
tables[i].classList.add('hidden');
}
}
}
/** Display items in menu /** Display items in menu
* @param MouseEvent * @param MouseEvent

View File

@@ -623,6 +623,7 @@ qsl('div').onclick = whisperClick;", "")
if (!$table_status) { if (!$table_status) {
echo "<p class='message'>" . lang('No tables.') . "\n"; echo "<p class='message'>" . lang('No tables.') . "\n";
} else { } else {
$this->printTablesFilter();
$this->tablesPrint($table_status); $this->tablesPrint($table_status);
} }
} }
@@ -632,19 +633,32 @@ qsl('div').onclick = whisperClick;", "")
function databasesPrint($missing) { function databasesPrint($missing) {
} }
function tablesPrint($tables) { function printTablesFilter()
echo "<ul id='tables'>"; {
echo script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});"); global $adminer;
echo "<div class='tables-filter jsonly'>"
. "<input id='tables-filter' autocomplete='off' placeholder='" . lang('Table') . "'>"
. script("initTablesFilter(" . json_encode($adminer->database()) . ");")
. "</div>\n";
}
function tablesPrint(array $tables) {
echo "<ul id='tables'>" . script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");
foreach ($tables as $row) { foreach ($tables as $row) {
echo '<li>'; // Skip views and tables without a name.
$name = $this->tableName($row); if (!isset($row["Engine"]) || ($name = $this->tableName($row)) == "") {
if (isset($row["Engine"]) && $name != "") { // ignore views and tables without name continue;
echo "<a href='" . h(ME) . 'select=' . urlencode($row["Name"]) . "'"
. bold($_GET["select"] == $row["Name"] || $_GET["edit"] == $row["Name"], "select")
. " title='" . lang('Select data') . "'>$name</a>\n"
;
} }
$active = $_GET["select"] == $row["Name"] || $_GET["edit"] == $row["Name"];
echo '<li><a href="' . h(ME) . 'select=' . urlencode($row["Name"]) . '"'
. bold($active, "select")
. " title='" . lang('Select data') . "' data-main='true'>$name</a></li>\n";
} }
echo "</ul>\n"; echo "</ul>\n";
} }
@@ -658,6 +672,8 @@ qsl('div').onclick = whisperClick;", "")
} }
} }
} }
return null;
} }
function _foreignKeyOptions($table, $column, $value = null) { function _foreignKeyOptions($table, $column, $value = null) {

View File

@@ -395,7 +395,7 @@ class AdminerPlugin extends Adminer {
return $this->_applyPlugin(__FUNCTION__, $args); return $this->_applyPlugin(__FUNCTION__, $args);
} }
function tablesPrint($tables) { function tablesPrint(array $tables) {
$args = func_get_args(); $args = func_get_args();
return $this->_applyPlugin(__FUNCTION__, $args); return $this->_applyPlugin(__FUNCTION__, $args);
} }

View File

@@ -1,69 +0,0 @@
<?php
/** Use filter in tables list
* @link https://www.adminer.org/plugins/#use
* @author Jakub Vrana, https://www.vrana.cz/
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
* @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other)
*/
class AdminerTablesFilter {
function tablesPrint($tables) { ?>
<script<?php echo nonce(); ?>>
var tablesFilterTimeout = null;
var tablesFilterValue = '';
function tablesFilter(){
var value = qs('#filter-field').value.toLowerCase();
if (value == tablesFilterValue) {
return;
}
tablesFilterValue = value;
if (value != '') {
var reg = (value + '').replace(/([\\\.\+\*\?\[\^\]\$\(\)\{\}\=\!\<\>\|\:])/g, '\\$1');
reg = new RegExp('('+ reg + ')', 'gi');
}
if (sessionStorage) {
sessionStorage.setItem('adminer_tables_filter', value);
}
var tables = qsa('li', qs('#tables'));
for (var i = 0; i < tables.length; i++) {
var a = null;
var text = tables[i].getAttribute('data-table-name');
if (text == null) {
a = qsa('a', tables[i])[1];
text = a.innerHTML.trim();
tables[i].setAttribute('data-table-name', text);
a.setAttribute('data-link', 'main');
} else {
a = qs('a[data-link="main"]', tables[i]);
}
if (value == '') {
tables[i].className = '';
a.innerHTML = text;
} else {
tables[i].className = (text.toLowerCase().indexOf(value) == -1 ? 'hidden' : '');
a.innerHTML = text.replace(reg, '<strong>$1</strong>');
}
}
}
function tablesFilterInput() {
window.clearTimeout(tablesFilterTimeout);
tablesFilterTimeout = window.setTimeout(tablesFilter, 200);
}
sessionStorage && document.addEventListener('DOMContentLoaded', function () {
var db = qs('#dbs').querySelector('select');
db = db.options[db.selectedIndex].text;
if (db == sessionStorage.getItem('adminer_tables_filter_db') && sessionStorage.getItem('adminer_tables_filter')){
qs('#filter-field').value = sessionStorage.getItem('adminer_tables_filter');
tablesFilter();
}
sessionStorage.setItem('adminer_tables_filter_db', db);
});
</script>
<p class="jsonly"><input id="filter-field" autocomplete="off"><?php echo script("qs('#filter-field').oninput = tablesFilterInput;"); ?>
<?php
}
}