309 lines
8.8 KiB
HTML
309 lines
8.8 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Keyboard Support Test</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
max-width: 1200px;
|
|
margin: 20px auto;
|
|
padding: 0 20px;
|
|
}
|
|
|
|
.test-container {
|
|
border: 2px solid #333;
|
|
padding: 20px;
|
|
margin: 20px 0;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.test-element {
|
|
background-color: #f0f0f0;
|
|
border: 2px solid #999;
|
|
padding: 30px;
|
|
text-align: center;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
margin: 10px 0;
|
|
}
|
|
|
|
.test-element:focus {
|
|
background-color: #e3f2fd;
|
|
border-color: #2196F3;
|
|
outline: none;
|
|
}
|
|
|
|
.log-container {
|
|
background-color: #1e1e1e;
|
|
color: #d4d4d4;
|
|
padding: 15px;
|
|
border-radius: 5px;
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
font-family: 'Courier New', monospace;
|
|
font-size: 14px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.log-entry {
|
|
margin: 5px 0;
|
|
padding: 5px;
|
|
border-left: 3px solid #4CAF50;
|
|
padding-left: 10px;
|
|
}
|
|
|
|
.log-entry.focus {
|
|
border-left-color: #2196F3;
|
|
}
|
|
|
|
.log-entry.no-focus {
|
|
border-left-color: #FF9800;
|
|
}
|
|
|
|
.shortcuts-list {
|
|
background-color: #fff3cd;
|
|
border: 1px solid #ffc107;
|
|
padding: 15px;
|
|
border-radius: 5px;
|
|
margin: 10px 0;
|
|
}
|
|
|
|
.shortcuts-list h3 {
|
|
margin-top: 0;
|
|
}
|
|
|
|
.shortcuts-list ul {
|
|
margin: 10px 0;
|
|
padding-left: 20px;
|
|
}
|
|
|
|
.shortcuts-list code {
|
|
background-color: #f5f5f5;
|
|
padding: 2px 6px;
|
|
border-radius: 3px;
|
|
font-family: 'Courier New', monospace;
|
|
}
|
|
|
|
.clear-button {
|
|
background-color: #f44336;
|
|
color: white;
|
|
border: none;
|
|
padding: 10px 20px;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.clear-button:hover {
|
|
background-color: #d32f2f;
|
|
}
|
|
|
|
h1, h2 {
|
|
color: #333;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Keyboard Support Test Page</h1>
|
|
|
|
<div class="shortcuts-list">
|
|
<h3>📋 Configured Shortcuts (with HTMX options)</h3>
|
|
<p><strong>Simple keys:</strong></p>
|
|
<ul>
|
|
<li><code>a</code> - Simple key A (POST to /test/key-a)</li>
|
|
<li><code>esc</code> - Escape key (POST)</li>
|
|
</ul>
|
|
<p><strong>Simultaneous combinations with HTMX options:</strong></p>
|
|
<ul>
|
|
<li><code>Ctrl+S</code> - Save (POST with swap: innerHTML)</li>
|
|
<li><code>Ctrl+C</code> - Copy (POST with target: #result, swap: outerHTML)</li>
|
|
</ul>
|
|
<p><strong>Sequences with various configs:</strong></p>
|
|
<ul>
|
|
<li><code>A B</code> - Sequence (POST with extra values: {"extra": "data"})</li>
|
|
<li><code>A B C</code> - Triple sequence (GET request)</li>
|
|
<li><code>shift shift</code> - Press Shift twice in sequence</li>
|
|
</ul>
|
|
<p><strong>Complex:</strong></p>
|
|
<ul>
|
|
<li><code>Ctrl+C C</code> - Ctrl+C then C alone</li>
|
|
<li><code>Ctrl+C Ctrl+C</code> - Ctrl+C twice</li>
|
|
</ul>
|
|
<p><strong>Tip:</strong> Check the log to see how HTMX options (target, swap, extra values) are passed!</p>
|
|
</div>
|
|
|
|
<div class="test-container">
|
|
<h2>Test Input (typing should work normally here)</h2>
|
|
<input type="text" placeholder="Try typing Ctrl+C, Ctrl+A here - should work normally" style="width: 100%; padding: 10px; font-size: 14px;">
|
|
<p style="margin-top: 10px; padding: 10px; background-color: #e3f2fd; border-left: 4px solid #2196F3; border-radius: 3px;">
|
|
<strong>Parameters Explained:</strong><br>
|
|
• <code>has_focus</code>: Whether the registered element itself has focus<br>
|
|
• <code>is_inside</code>: Whether the focus is on the registered element or any of its children<br>
|
|
<em>Example: If focus is on this input and its parent div is registered, has_focus=false but is_inside=true</em>
|
|
</p>
|
|
</div>
|
|
|
|
<div class="test-container">
|
|
<h2>Test Element 1</h2>
|
|
<div id="test-element" class="test-element" tabindex="0">
|
|
Click me to focus, then try keyboard shortcuts
|
|
</div>
|
|
</div>
|
|
|
|
<div class="test-container">
|
|
<h2>Test Element 2 (also listens to ESC and Shift Shift)</h2>
|
|
<div id="test-element-2" class="test-element" tabindex="0">
|
|
This element also responds to ESC and Shift Shift
|
|
</div>
|
|
<button class="clear-button" onclick="removeElement2()" style="background-color: #FF5722; margin-top: 10px;">
|
|
Remove Element 2 Keyboard Support
|
|
</button>
|
|
</div>
|
|
|
|
<div class="test-container">
|
|
<h2>Event Log</h2>
|
|
<button class="clear-button" onclick="clearLog()">Clear Log</button>
|
|
<div id="log" class="log-container"></div>
|
|
</div>
|
|
|
|
<!-- Include htmx -->
|
|
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
|
|
|
<!-- Mock htmx.ajax for testing -->
|
|
<script>
|
|
// Store original htmx.ajax if it exists
|
|
const originalHtmxAjax = window.htmx && window.htmx.ajax;
|
|
|
|
// Override htmx.ajax for testing purposes
|
|
if (window.htmx) {
|
|
window.htmx.ajax = function(method, url, config) {
|
|
const timestamp = new Date().toLocaleTimeString();
|
|
const hasFocus = config.values.has_focus;
|
|
const isInside = config.values.is_inside;
|
|
const combination = config.values.combination;
|
|
|
|
// Build details string with all config options
|
|
const details = [
|
|
`Combination: "${combination}"`,
|
|
`Element has focus: ${hasFocus}`,
|
|
`Focus inside element: ${isInside}`
|
|
];
|
|
|
|
if (config.target) {
|
|
details.push(`Target: ${config.target}`);
|
|
}
|
|
if (config.swap) {
|
|
details.push(`Swap: ${config.swap}`);
|
|
}
|
|
if (config.values) {
|
|
const extraVals = Object.keys(config.values).filter(k => k !== 'combination' && k !== 'has_focus');
|
|
if (extraVals.length > 0) {
|
|
details.push(`Extra values: ${JSON.stringify(extraVals.reduce((obj, k) => ({...obj, [k]: config.values[k]}), {}))}`);
|
|
}
|
|
}
|
|
|
|
logEvent(
|
|
`[${timestamp}] ${method} ${url}`,
|
|
...details,
|
|
hasFocus
|
|
);
|
|
|
|
// Uncomment below to use real htmx.ajax if you have a backend
|
|
// if (originalHtmxAjax) {
|
|
// originalHtmxAjax.call(this, method, url, config);
|
|
// }
|
|
};
|
|
}
|
|
|
|
function logEvent(title, ...details) {
|
|
const log = document.getElementById('log');
|
|
const hasFocus = details[details.length - 1];
|
|
|
|
const entry = document.createElement('div');
|
|
entry.className = `log-entry ${hasFocus ? 'focus' : 'no-focus'}`;
|
|
entry.innerHTML = `
|
|
<strong>${title}</strong><br>
|
|
${details.slice(0, -1).join('<br>')}
|
|
`;
|
|
|
|
log.insertBefore(entry, log.firstChild);
|
|
}
|
|
|
|
function clearLog() {
|
|
document.getElementById('log').innerHTML = '';
|
|
}
|
|
|
|
function removeElement2() {
|
|
remove_keyboard_support('test-element-2');
|
|
logEvent('Element 2 keyboard support removed',
|
|
'ESC and Shift Shift no longer trigger for Element 2',
|
|
'Element 1 still active', false);
|
|
// Disable the button
|
|
event.target.disabled = true;
|
|
event.target.textContent = 'Keyboard Support Removed';
|
|
}
|
|
</script>
|
|
|
|
<!-- Include keyboard support script -->
|
|
<script src="keyboard_support.js"></script>
|
|
|
|
<!-- Initialize keyboard support -->
|
|
<script>
|
|
const combinations = {
|
|
"a": {
|
|
"hx-post": "/test/key-a"
|
|
},
|
|
"Ctrl+S": {
|
|
"hx-post": "/test/save",
|
|
"hx-swap": "innerHTML"
|
|
},
|
|
"Ctrl+C": {
|
|
"hx-post": "/test/copy",
|
|
"hx-target": "#result",
|
|
"hx-swap": "outerHTML"
|
|
},
|
|
"A B": {
|
|
"hx-post": "/test/sequence-ab",
|
|
"hx-vals": {"extra": "data"}
|
|
},
|
|
"A B C": {
|
|
"hx-get": "/test/sequence-abc"
|
|
},
|
|
"Ctrl+C C": {
|
|
"hx-post": "/test/complex-ctrl-c-c"
|
|
},
|
|
"Ctrl+C Ctrl+C": {
|
|
"hx-post": "/test/complex-ctrl-c-twice"
|
|
},
|
|
"shift shift": {
|
|
"hx-post": "/test/shift-shift"
|
|
},
|
|
"esc": {
|
|
"hx-post": "/test/escape"
|
|
}
|
|
};
|
|
|
|
add_keyboard_support('test-element', JSON.stringify(combinations));
|
|
|
|
// Add second element that also listens to ESC and shift shift
|
|
const combinations2 = {
|
|
"esc": {
|
|
"hx-post": "/test/escape-element2"
|
|
},
|
|
"shift shift": {
|
|
"hx-post": "/test/shift-shift-element2"
|
|
}
|
|
};
|
|
|
|
add_keyboard_support('test-element-2', JSON.stringify(combinations2));
|
|
|
|
// Log initial state
|
|
logEvent('Keyboard support initialized',
|
|
'Element 1: All shortcuts configured with HTMX options',
|
|
'Element 2: ESC and Shift Shift (will trigger simultaneously with Element 1)',
|
|
'Smart timeout enabled: waits 500ms only if longer sequence exists', false);
|
|
</script>
|
|
</body>
|
|
</html> |