mirror of
https://github.com/vrana/adminer.git
synced 2025-08-30 17:50:00 +02:00
Show help popup after a short delay, refactoring
This commit is contained in:
@@ -183,7 +183,7 @@ foreach ($engines as $engine) {
|
|||||||
<?php if (support("columns") || $TABLE == "") { ?>
|
<?php if (support("columns") || $TABLE == "") { ?>
|
||||||
<?php echo lang('Table name'); ?>: <input name="name" data-maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
|
<?php echo lang('Table name'); ?>: <input name="name" data-maxlength="64" value="<?php echo h($row["name"]); ?>" autocapitalize="off">
|
||||||
<?php if ($TABLE == "" && !$_POST) { echo script("focus(qs('#form')['name']);"); } ?>
|
<?php if ($TABLE == "" && !$_POST) { echo script("focus(qs('#form')['name']);"); } ?>
|
||||||
<?php echo ($engines ? "<select name='Engine'>" . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "</select>" . on_help("getTarget(event).value", 1) . script("qsl('select').onchange = helpClose;") : ""); ?>
|
<?php echo ($engines ? "<select name='Engine'>" . optionlist(array("" => "(" . lang('engine') . ")") + $engines, $row["Engine"]) . "</select>" . help_script_command("value", true) : ""); ?>
|
||||||
<?php echo ($collations && !preg_match("~sqlite|mssql~", $jush) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>
|
<?php echo ($collations && !preg_match("~sqlite|mssql~", $jush) ? html_select("Collation", array("" => "(" . lang('collation') . ")") + $collations, $row["Collation"]) : ""); ?>
|
||||||
<input type="submit" value="<?php echo lang('Save'); ?>">
|
<input type="submit" value="<?php echo lang('Save'); ?>">
|
||||||
<?php } ?>
|
<?php } ?>
|
||||||
@@ -221,7 +221,7 @@ if (support("partitioning")) {
|
|||||||
print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
|
print_fieldset("partition", lang('Partition by'), $row["partition_by"]);
|
||||||
?>
|
?>
|
||||||
<p>
|
<p>
|
||||||
<?php echo "<select name='partition_by'>" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "</select>" . on_help("getTarget(event).value.replace(/./, 'PARTITION BY \$&')", 1) . script("qsl('select').onchange = partitionByChange;"); ?>
|
<?php echo "<select name='partition_by'>" . optionlist(array("" => "") + $partition_by, $row["partition_by"]) . "</select>" . help_script_command("value.replace(/./, 'PARTITION BY \$&')", true) . script("qsl('select').onchange = partitionByChange;"); ?>
|
||||||
(<input name="partition" value="<?php echo h($row["partition"]); ?>">)
|
(<input name="partition" value="<?php echo h($row["partition"]); ?>">)
|
||||||
<?php echo lang('Partitions'); ?>: <input type="number" name="partitions" class="size<?php echo ($partition_table || !$row["partition_by"] ? " hidden" : ""); ?>" value="<?php echo h($row["partitions"]); ?>">
|
<?php echo lang('Partitions'); ?>: <input type="number" name="partitions" class="size<?php echo ($partition_table || !$row["partition_by"] ? " hidden" : ""); ?>" value="<?php echo h($row["partitions"]); ?>">
|
||||||
<table cellspacing="0" id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>>
|
<table cellspacing="0" id="partition-table"<?php echo ($partition_table ? "" : " class='hidden'"); ?>>
|
||||||
|
@@ -147,17 +147,17 @@ if ($adminer->homepage()) {
|
|||||||
echo "</div>\n";
|
echo "</div>\n";
|
||||||
if (!information_schema(DB)) {
|
if (!information_schema(DB)) {
|
||||||
echo "<div class='footer'><div>\n";
|
echo "<div class='footer'><div>\n";
|
||||||
$vacuum = "<input type='submit' value='" . lang('Vacuum') . "'> " . on_help("'VACUUM'");
|
$vacuum = "<input type='submit' value='" . lang('Vacuum') . "'> " . help_script("VACUUM");
|
||||||
$optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'> " . on_help($jush == "sql" ? "'OPTIMIZE TABLE'" : "'VACUUM OPTIMIZE'");
|
$optimize = "<input type='submit' name='optimize' value='" . lang('Optimize') . "'> " . help_script($jush == "sql" ? "OPTIMIZE TABLE" : "VACUUM OPTIMIZE");
|
||||||
echo "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>"
|
echo "<fieldset><legend>" . lang('Selected') . " <span id='selected'></span></legend><div>"
|
||||||
. ($jush == "sqlite" ? $vacuum
|
. ($jush == "sqlite" ? $vacuum
|
||||||
: ($jush == "pgsql" ? $vacuum . $optimize
|
: ($jush == "pgsql" ? $vacuum . $optimize
|
||||||
: ($jush == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> " . on_help("'ANALYZE TABLE'") . $optimize
|
: ($jush == "sql" ? "<input type='submit' value='" . lang('Analyze') . "'> " . help_script("ANALYZE TABLE") . $optimize
|
||||||
. "<input type='submit' name='check' value='" . lang('Check') . "'> " . on_help("'CHECK TABLE'")
|
. "<input type='submit' name='check' value='" . lang('Check') . "'> " . help_script("CHECK TABLE")
|
||||||
. "<input type='submit' name='repair' value='" . lang('Repair') . "'> " . on_help("'REPAIR TABLE'")
|
. "<input type='submit' name='repair' value='" . lang('Repair') . "'> " . help_script("REPAIR TABLE")
|
||||||
: "")))
|
: "")))
|
||||||
. "<input type='submit' name='truncate' value='" . lang('Truncate') . "'> " . on_help($jush == "sqlite" ? "'DELETE'" : "'TRUNCATE" . ($jush == "pgsql" ? "'" : " TABLE'")) . confirm()
|
. "<input type='submit' name='truncate' value='" . lang('Truncate') . "'> " . help_script($jush == "sqlite" ? "DELETE" : ("TRUNCATE" . ($jush == "pgsql" ? "" : " TABLE"))) . confirm()
|
||||||
. "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . on_help("'DROP TABLE'") . confirm() . "\n";
|
. "<input type='submit' name='drop' value='" . lang('Drop') . "'>" . help_script("DROP TABLE") . confirm() . "\n";
|
||||||
$databases = (support("scheme") ? $adminer->schemas() : $adminer->databases());
|
$databases = (support("scheme") ? $adminer->schemas() : $adminer->databases());
|
||||||
if (count($databases) != 1 && $jush != "sqlite") {
|
if (count($databases) != 1 && $jush != "sqlite") {
|
||||||
$db = (isset($_POST["target"]) ? $_POST["target"] : (support("scheme") ? $_GET["ns"] : DB));
|
$db = (isset($_POST["target"]) ? $_POST["target"] : (support("scheme") ? $_GET["ns"] : DB));
|
||||||
|
@@ -424,8 +424,8 @@ class Adminer {
|
|||||||
echo "<select name='columns[$i][fun]'>",
|
echo "<select name='columns[$i][fun]'>",
|
||||||
optionlist([-1 => ""] + array_filter([lang('Functions') => $functions, lang('Aggregation') => $grouping]), $val["fun"]),
|
optionlist([-1 => ""] + array_filter([lang('Functions') => $functions, lang('Aggregation') => $grouping]), $val["fun"]),
|
||||||
"</select>",
|
"</select>",
|
||||||
on_help("getTarget(event).value && getTarget(event).value.replace(/ |\$/, '(') + ')'", 1),
|
help_script_command("value && value.replace(/ |\$/, '(') + ')'", true),
|
||||||
script("qsl('select').onchange = (event) => { helpClose();" . ($key !== "" ? "" : " qsl('select, input:not(.remove)', event.target.parentNode).onchange();") . " };", ""),
|
script("qsl('select').onchange = (event) => { " . ($key !== "" ? "" : " qsl('select, input:not(.remove)', event.target.parentNode).onchange();") . " };", ""),
|
||||||
"($column)";
|
"($column)";
|
||||||
} else {
|
} else {
|
||||||
echo $column;
|
echo $column;
|
||||||
|
@@ -54,7 +54,7 @@ function page_header($title, $error = "", $breadcrumb = [], $title2 = "") {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="help" class="jush-<?php echo $jush; ?> jsonly hidden"></div>
|
<div id="help" class="jush-<?php echo $jush; ?> jsonly hidden"></div>
|
||||||
<?php echo script("mixin(qs('#help'), {onmouseover: function () { helpOpen = 1; }, onmouseout: helpMouseout});"); ?>
|
<?php echo script("initHelpPopup();"); ?>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<?php
|
<?php
|
||||||
|
@@ -967,7 +967,7 @@ function input($field, $value, $function) {
|
|||||||
$has_function = (in_array($function, $functions) || isset($functions[$function]));
|
$has_function = (in_array($function, $functions) || isset($functions[$function]));
|
||||||
echo (count($functions) > 1
|
echo (count($functions) > 1
|
||||||
? "<select name='function[$name]' $disabled>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
|
? "<select name='function[$name]' $disabled>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
|
||||||
. on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1)
|
. help_script_command("value.replace(/^SQL\$/, '')", true)
|
||||||
. script("qsl('select').onchange = functionChange;", "")
|
. script("qsl('select').onchange = functionChange;", "")
|
||||||
: h(reset($functions))
|
: h(reset($functions))
|
||||||
) . '<td>';
|
) . '<td>';
|
||||||
@@ -1486,13 +1486,26 @@ function lzw_decompress($binary) {
|
|||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return events to display help on mouse over
|
/**
|
||||||
* @param string JS expression
|
* @param string $text Help text.
|
||||||
* @param bool JS expression
|
* @param bool $side Side position.
|
||||||
* @return string
|
*
|
||||||
*/
|
* @return string
|
||||||
function on_help($command, $side = 0) {
|
*/
|
||||||
return script("mixin(qsl('select, input'), {onmouseover: function (event) { helpMouseover.call(this, event, $command, $side) }, onmouseout: helpMouseout});", "");
|
function help_script($text, $side = false)
|
||||||
|
{
|
||||||
|
return script("initHelpFor(qsl('select, input'), '" . h($text) . "', $side);", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $command JS expression for returning the help text.
|
||||||
|
* @param bool $side Side position.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function help_script_command($command, $side = false)
|
||||||
|
{
|
||||||
|
return script("initHelpFor(qsl('select, input'), (value) => { return $command; }, $side);", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Print edit data form
|
/** Print edit data form
|
||||||
|
@@ -236,11 +236,13 @@ function editFields() {
|
|||||||
els = qsa('[name$="[type]"]');
|
els = qsa('[name$="[type]"]');
|
||||||
for (var i = 0; i < els.length; i++) {
|
for (var i = 0; i < els.length; i++) {
|
||||||
mixin(els[i], {
|
mixin(els[i], {
|
||||||
onfocus: function () { lastType = selectValue(this); },
|
onfocus: () => {
|
||||||
|
lastType = selectValue(this);
|
||||||
|
},
|
||||||
onchange: editingTypeChange,
|
onchange: editingTypeChange,
|
||||||
onmouseover: function (event) { helpMouseover.call(this, event, getTarget(event).value, 1) },
|
|
||||||
onmouseout: helpMouseout
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
initHelpFor(els[i], (value) => { return value; }, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +417,6 @@ function editingTypeChange() {
|
|||||||
alterClass(el, 'hidden', !/`/.test(text));
|
alterClass(el, 'hidden', !/`/.test(text));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
helpClose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Mark length as required
|
/** Mark length as required
|
||||||
@@ -488,7 +489,6 @@ function partitionByChange() {
|
|||||||
var partitionTable = /RANGE|LIST/.test(selectValue(this));
|
var partitionTable = /RANGE|LIST/.test(selectValue(this));
|
||||||
alterClass(this.form['partitions'], 'hidden', partitionTable || !this.selectedIndex);
|
alterClass(this.form['partitions'], 'hidden', partitionTable || !this.selectedIndex);
|
||||||
alterClass(qs('#partition-table'), 'hidden', !partitionTable);
|
alterClass(qs('#partition-table'), 'hidden', !partitionTable);
|
||||||
helpClose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Add next partition row
|
/** Add next partition row
|
||||||
@@ -732,48 +732,107 @@ function schemaMouseup(event, db) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Help.
|
||||||
|
(function() {
|
||||||
|
let openTimeout = null;
|
||||||
|
let closeTimeout = null;
|
||||||
|
let helpVisible = false;
|
||||||
|
|
||||||
var helpOpen, helpIgnore; // when mouse outs <option> then it mouse overs border of <select> - ignore it
|
window.initHelpPopup = function () {
|
||||||
|
const help = gid("help");
|
||||||
|
|
||||||
/** Display help
|
help.addEventListener("mouseenter", () => {
|
||||||
* @param MouseEvent
|
clearTimeout(closeTimeout);
|
||||||
* @param string
|
closeTimeout = null;
|
||||||
* @param bool display on left side (otherwise on top)
|
});
|
||||||
* @this HTMLElement
|
|
||||||
*/
|
|
||||||
function helpMouseover(event, text, side) {
|
|
||||||
var target = getTarget(event);
|
|
||||||
if (!text) {
|
|
||||||
helpClose();
|
|
||||||
} else if (window.jush && (!helpIgnore || this !== target)) {
|
|
||||||
helpOpen = 1;
|
|
||||||
var help = qs('#help');
|
|
||||||
help.innerHTML = text;
|
|
||||||
jush.highlight_tag([ help ]);
|
|
||||||
alterClass(help, 'hidden');
|
|
||||||
var rect = target.getBoundingClientRect();
|
|
||||||
var body = document.documentElement;
|
|
||||||
help.style.top = (body.scrollTop + rect.top - (side ? (help.offsetHeight - target.offsetHeight) / 2 : help.offsetHeight)) + 'px';
|
|
||||||
help.style.left = (body.scrollLeft + rect.left - (side ? help.offsetWidth : (help.offsetWidth - target.offsetWidth) / 2)) + 'px';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Close help after timeout
|
help.addEventListener("mouseleave", hideHelp);
|
||||||
* @param MouseEvent
|
};
|
||||||
* @this HTMLElement
|
|
||||||
*/
|
/**
|
||||||
function helpMouseout(event) {
|
* @param {HTMLElement} element
|
||||||
helpOpen = 0;
|
* @param {string|function} content
|
||||||
helpIgnore = (this !== getTarget(event));
|
* @param {boolean} side Displays on left side (otherwise on top).
|
||||||
setTimeout(function () {
|
*/
|
||||||
if (!helpOpen) {
|
window.initHelpFor = function(element, content, side = false) {
|
||||||
helpClose();
|
const withCallback = typeof content === "function";
|
||||||
|
|
||||||
|
element.addEventListener("mouseenter", (event) => {
|
||||||
|
showHelp(event.target, withCallback ? content(event.target.value) : content, side)
|
||||||
|
});
|
||||||
|
|
||||||
|
element.addEventListener("mouseleave", hideHelp);
|
||||||
|
element.addEventListener("blur", hideHelp);
|
||||||
|
|
||||||
|
if (withCallback) {
|
||||||
|
element.addEventListener("change", hideHelp);
|
||||||
}
|
}
|
||||||
}, 200);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
/** Close help
|
/**
|
||||||
*/
|
* Displays help popup after a small delay.
|
||||||
function helpClose() {
|
*
|
||||||
alterClass(qs('#help'), 'hidden', true);
|
* @param {HTMLElement} element
|
||||||
}
|
* @param {string} text
|
||||||
|
* @param {boolean} side display on left side (otherwise on top)
|
||||||
|
*/
|
||||||
|
function showHelp(element, text, side) {
|
||||||
|
if (!text) {
|
||||||
|
hideHelp();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSorting() || !window.jush) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearTimeout(openTimeout);
|
||||||
|
openTimeout = null;
|
||||||
|
clearTimeout(closeTimeout);
|
||||||
|
closeTimeout = null;
|
||||||
|
|
||||||
|
const help = gid("help");
|
||||||
|
help.innerHTML = text;
|
||||||
|
jush.highlight_tag([help]);
|
||||||
|
|
||||||
|
// Display help briefly to calculate position properly.
|
||||||
|
help.classList.remove("hidden");
|
||||||
|
|
||||||
|
const rect = element.getBoundingClientRect();
|
||||||
|
const root = document.documentElement;
|
||||||
|
|
||||||
|
help.style.top = (root.scrollTop + rect.top - (side ? (help.offsetHeight - element.offsetHeight) / 2 : help.offsetHeight)) + 'px';
|
||||||
|
help.style.left = (root.scrollLeft + rect.left - (side ? help.offsetWidth : (help.offsetWidth - element.offsetWidth) / 2)) + 'px';
|
||||||
|
|
||||||
|
if (helpVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
help.classList.add("hidden");
|
||||||
|
|
||||||
|
openTimeout = setTimeout(() => {
|
||||||
|
gid("help").classList.remove("hidden");
|
||||||
|
|
||||||
|
helpVisible = true;
|
||||||
|
openTimeout = null;
|
||||||
|
}, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the help popup after a small delay.
|
||||||
|
*/
|
||||||
|
function hideHelp() {
|
||||||
|
if (openTimeout) {
|
||||||
|
clearTimeout(openTimeout);
|
||||||
|
openTimeout = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeTimeout = setTimeout(() => {
|
||||||
|
gid("help").classList.add("hidden");
|
||||||
|
|
||||||
|
helpVisible = false;
|
||||||
|
closeTimeout = null;
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
@@ -544,13 +544,13 @@ function selectSearchSearch() {
|
|||||||
|
|
||||||
// Sorting.
|
// Sorting.
|
||||||
(function() {
|
(function() {
|
||||||
let placeholderRow, nextRow, dragHelper;
|
let placeholderRow = null, nextRow = null, dragHelper = null;
|
||||||
let startY, minY, maxY;
|
let startY, minY, maxY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes sortable list of DIV elements.
|
* Initializes sortable list of DIV elements.
|
||||||
*
|
*
|
||||||
* @param {string} parentId
|
* @param {string} parentSelector
|
||||||
*/
|
*/
|
||||||
window.initSortable = function(parentSelector) {
|
window.initSortable = function(parentSelector) {
|
||||||
const parent = qs(parentSelector);
|
const parent = qs(parentSelector);
|
||||||
@@ -576,6 +576,10 @@ function selectSearchSearch() {
|
|||||||
handle.addEventListener("touchstart", (event) => { startSorting(row, event) });
|
handle.addEventListener("touchstart", (event) => { startSorting(row, event) });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.isSorting = function () {
|
||||||
|
return dragHelper !== null;
|
||||||
|
};
|
||||||
|
|
||||||
function startSorting(row, event) {
|
function startSorting(row, event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
@@ -670,6 +674,8 @@ function selectSearchSearch() {
|
|||||||
placeholderRow.parentNode.insertBefore(dragHelper.tagName === "TABLE" ? dragHelper.firstChild : dragHelper, placeholderRow);
|
placeholderRow.parentNode.insertBefore(dragHelper.tagName === "TABLE" ? dragHelper.firstChild : dragHelper, placeholderRow);
|
||||||
placeholderRow.remove();
|
placeholderRow.remove();
|
||||||
|
|
||||||
|
placeholderRow = nextRow = dragHelper = null;
|
||||||
|
|
||||||
window.removeEventListener("mousemove", updateSorting);
|
window.removeEventListener("mousemove", updateSorting);
|
||||||
window.removeEventListener("touchmove", updateSorting);
|
window.removeEventListener("touchmove", updateSorting);
|
||||||
|
|
||||||
@@ -822,7 +828,6 @@ function functionChange() {
|
|||||||
|
|
||||||
// Undefined with the set data type.
|
// Undefined with the set data type.
|
||||||
if (!input) {
|
if (!input) {
|
||||||
helpClose();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -852,8 +857,6 @@ function functionChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
oninput({target: input});
|
oninput({target: input});
|
||||||
|
|
||||||
helpClose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -6,13 +6,14 @@ function messagesPrint() {
|
|||||||
function selectFieldChange() {
|
function selectFieldChange() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var helpOpen;
|
// Help.
|
||||||
|
(function() {
|
||||||
|
window.initHelpPopup = function () {
|
||||||
|
};
|
||||||
|
|
||||||
function helpMouseover() {
|
window.initHelpFor = function(element, content, side = false) {
|
||||||
}
|
};
|
||||||
|
})();
|
||||||
function helpMouseout() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Display typeahead
|
/** Display typeahead
|
||||||
* @param string
|
* @param string
|
||||||
|
Reference in New Issue
Block a user