vibetunnel/web/public/tests/mobile-selection-test.html
2025-06-17 22:10:48 +02:00

300 lines
No EOL
10 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<title>Mobile Text Selection Test</title>
<style>
body {
font-family: monospace;
padding: 20px;
line-height: 1.5;
}
.test-text {
background: #f0f0f0;
padding: 20px;
margin: 10px 0;
border-radius: 5px;
}
.selectable {
user-select: text;
-webkit-user-select: text;
-webkit-touch-callout: default;
}
.non-selectable {
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
}
button {
padding: 10px;
margin: 5px;
font-size: 16px;
}
#log {
background: #000;
color: #0f0;
padding: 10px;
height: 200px;
overflow-y: auto;
font-family: monospace;
font-size: 12px;
}
</style>
</head>
<body>
<h1>Mobile Text Selection Test</h1>
<div class="test-text selectable" id="test1">
This text should be selectable normally. Try long pressing on it.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
You should see selection handles and context menu.
</div>
<div class="test-text non-selectable" id="test2">
This text is NOT selectable by default (user-select: none).
We'll try to programmatically select it on long press.
</div>
<button onclick="testProgrammaticSelection()">Test Programmatic Selection</button>
<button onclick="testTouchEvents()">Test Touch Events</button>
<button onclick="testMouseEvents()">Test Mouse Events</button>
<button onclick="clearSelection()">Clear Selection</button>
<button onclick="selectAll()">Select All</button>
<div id="log"></div>
<script>
function log(message) {
const logDiv = document.getElementById('log');
logDiv.innerHTML += new Date().toLocaleTimeString() + ': ' + message + '\n';
logDiv.scrollTop = logDiv.scrollHeight;
}
function testProgrammaticSelection() {
const element = document.getElementById('test2');
// Temporarily enable selection
element.style.userSelect = 'text';
element.style.webkitUserSelect = 'text';
element.style.webkitTouchCallout = 'default';
try {
const range = document.createRange();
const selection = window.getSelection();
selection.removeAllRanges();
if (element.firstChild) {
range.setStart(element.firstChild, 5);
range.setEnd(element.firstChild, 20);
selection.addRange(range);
log('Created programmatic selection: "' + selection.toString() + '"');
log('Range count: ' + selection.rangeCount);
// Try to trigger selection UI
setTimeout(() => {
// Method 1: Focus the element
element.focus();
log('Focused element');
// Method 2: Dispatch selectstart event
const selectStartEvent = new Event('selectstart', { bubbles: true });
element.dispatchEvent(selectStartEvent);
log('Dispatched selectstart event');
// Method 3: Dispatch selectionchange on document
const selectionChangeEvent = new Event('selectionchange');
document.dispatchEvent(selectionChangeEvent);
log('Dispatched selectionchange event');
}, 100);
} else {
log('No text node found');
}
} catch (error) {
log('Error: ' + error.message);
}
}
function clearSelection() {
const selection = window.getSelection();
selection.removeAllRanges();
log('Cleared selection');
}
function testTouchEvents() {
const element = document.getElementById('test2');
// Enable selection
element.style.userSelect = 'text';
element.style.webkitUserSelect = 'text';
element.style.webkitTouchCallout = 'default';
const rect = element.getBoundingClientRect();
const x = rect.left + rect.width / 2;
const y = rect.top + rect.height / 2;
try {
// Create touch events
const touchStart = new TouchEvent('touchstart', {
bubbles: true,
cancelable: true,
touches: [new Touch({
identifier: 1,
target: element,
clientX: x,
clientY: y
})]
});
element.dispatchEvent(touchStart);
log('Dispatched touchstart event');
// Hold for long press duration
setTimeout(() => {
const touchEnd = new TouchEvent('touchend', {
bubbles: true,
cancelable: true,
changedTouches: [new Touch({
identifier: 1,
target: element,
clientX: x,
clientY: y
})]
});
element.dispatchEvent(touchEnd);
log('Dispatched touchend after 600ms');
}, 600);
} catch (error) {
log('Touch events error: ' + error.message);
}
}
function testMouseEvents() {
const element = document.getElementById('test2');
// Enable selection
element.style.userSelect = 'text';
element.style.webkitUserSelect = 'text';
element.style.webkitTouchCallout = 'default';
const rect = element.getBoundingClientRect();
const x = rect.left + rect.width / 2;
const y = rect.top + rect.height / 2;
try {
// Mouse down
const mouseDown = new MouseEvent('mousedown', {
clientX: x,
clientY: y,
bubbles: true,
cancelable: true
});
element.dispatchEvent(mouseDown);
log('Dispatched mousedown');
// Small mouse move to start selection
setTimeout(() => {
const mouseMove = new MouseEvent('mousemove', {
clientX: x + 5,
clientY: y,
bubbles: true,
cancelable: true
});
element.dispatchEvent(mouseMove);
log('Dispatched mousemove');
// Mouse up
setTimeout(() => {
const mouseUp = new MouseEvent('mouseup', {
clientX: x + 5,
clientY: y,
bubbles: true,
cancelable: true
});
element.dispatchEvent(mouseUp);
log('Dispatched mouseup');
}, 100);
}, 50);
} catch (error) {
log('Mouse events error: ' + error.message);
}
}
function selectAll() {
const element = document.getElementById('test1');
try {
const range = document.createRange();
const selection = window.getSelection();
selection.removeAllRanges();
range.selectNodeContents(element);
selection.addRange(range);
log('Selected all content in test1');
} catch (error) {
log('Error: ' + error.message);
}
}
// Long press detection
let longPressTimer = null;
let startX, startY;
document.getElementById('test2').addEventListener('touchstart', function(e) {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
longPressTimer = setTimeout(() => {
log('Long press detected on test2');
testProgrammaticSelection();
}, 500);
log('Touch start on test2');
});
document.getElementById('test2').addEventListener('touchmove', function(e) {
const deltaX = Math.abs(e.touches[0].clientX - startX);
const deltaY = Math.abs(e.touches[0].clientY - startY);
if (deltaX > 5 || deltaY > 5) {
clearTimeout(longPressTimer);
log('Touch moved, cancelling long press');
}
});
document.getElementById('test2').addEventListener('touchend', function(e) {
clearTimeout(longPressTimer);
log('Touch end on test2');
});
// Log selection changes
document.addEventListener('selectionchange', function() {
const selection = window.getSelection();
if (selection.toString()) {
log('Selection changed: "' + selection.toString() + '"');
} else {
log('Selection cleared');
}
});
log('Mobile selection test loaded');
</script>
</body>
</html>