Add slider hover tooltip and CSV/paste import for custom arrays
This commit is contained in:
parent
1e812c86c6
commit
01a4840393
1 changed files with 99 additions and 2 deletions
|
|
@ -73,6 +73,24 @@
|
|||
cursor: pointer;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
/* ── Slider Tooltip ── */
|
||||
.slider-tooltip {
|
||||
position: fixed;
|
||||
background: var(--c-surface2, #1e2235);
|
||||
border: 1px solid var(--c-border, #2a2d3d);
|
||||
border-radius: 6px;
|
||||
padding: 3px 8px;
|
||||
font-size: 11px;
|
||||
font-family: monospace;
|
||||
color: var(--c-accent, #4a7cff);
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
transition: opacity 0.15s ease;
|
||||
z-index: 9999;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.slider-tooltip.visible { opacity: 1; }
|
||||
input[type="range"]::-webkit-slider-runnable-track {
|
||||
height: 6px;
|
||||
background: var(--c-surface2);
|
||||
|
|
@ -197,7 +215,7 @@
|
|||
<div class="flex-1"></div>
|
||||
<div class="text-center">
|
||||
<h1 class="title-text font-bold tracking-tight" style="color: var(--c-text); text-shadow: 0 0 40px rgba(74,124,255,0.3);">
|
||||
Sortier-Algorithmen <span style="font-size: 0.45em; font-weight: 400; opacity: 0.5; vertical-align: middle;">v0.2.8</span>
|
||||
Sortier-Algorithmen <span style="font-size: 0.45em; font-weight: 400; opacity: 0.5; vertical-align: middle;">v0.2.9</span>
|
||||
</h1>
|
||||
<p class="text-muted text-sm mt-0.5">Interaktive Visualisierung mit schrittweiser Animation</p>
|
||||
</div>
|
||||
|
|
@ -275,10 +293,14 @@
|
|||
<div class="space-y-1.5">
|
||||
<label for="customArray" class="label-text uppercase tracking-wider text-muted font-medium flex items-center gap-1.5">
|
||||
<i data-lucide="pencil" class="w-3.5 h-3.5"></i> Eigene Werte
|
||||
<span id="customArrayCount" class="text-[10px] text-muted ml-auto normal-case tracking-normal font-mono"></span>
|
||||
</label>
|
||||
<div class="flex gap-1.5">
|
||||
<input type="text" id="customArray" placeholder="z.B. 5, 3, 8, 1"
|
||||
<input type="text" id="customArray" placeholder="z.B. 5, 3, 8, 1 oder Mehrfachpaste"
|
||||
class="flex-1 min-w-0 bg-surface2 border border-border rounded-lg px-2 py-2 text-sm outline-none focus:border-accent focus:ring-1 focus:ring-accent/30 transition" style="color: var(--c-text);">
|
||||
<button id="btnPasteCustom" class="px-2.5 min-w-[36px] flex items-center justify-center rounded-lg border border-border bg-surface2 hover:bg-accent hover:border-accent hover:text-white transition-colors" style="color: var(--c-text);" title="Aus Zwischenablage einfügen" aria-label="Aus Zwischenablage einfügen">
|
||||
<i data-lucide="clipboard-paste" class="w-4 h-4"></i>
|
||||
</button>
|
||||
<button id="btnClearCustom" class="px-2.5 min-w-[36px] flex items-center justify-center rounded-lg border border-border bg-surface2 hover:bg-accent hover:border-accent hover:text-white transition-colors" style="color: var(--c-text);" title="Eigene Werte leeren">
|
||||
<i data-lucide="x" class="w-4 h-4"></i>
|
||||
</button>
|
||||
|
|
@ -316,6 +338,9 @@
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Floating Slider Tooltip -->
|
||||
<div id="sliderTooltip" class="slider-tooltip"></div>
|
||||
|
||||
<!-- Transport Buttons -->
|
||||
<section class="bg-surface border border-border rounded-xl p-4">
|
||||
<div class="grid grid-cols-4 sm:grid-cols-5 gap-2">
|
||||
|
|
@ -809,6 +834,8 @@ const $algoSelect = document.getElementById('algoSelect');
|
|||
const $presetSelect = document.getElementById('presetSelect');
|
||||
const $customArray = document.getElementById('customArray');
|
||||
const $btnClearCustom = document.getElementById('btnClearCustom');
|
||||
const $btnPasteCustom = document.getElementById('btnPasteCustom');
|
||||
const $customArrayCount = document.getElementById('customArrayCount');
|
||||
const $sizeSlider = document.getElementById('sizeSlider');
|
||||
const $speedSlider = document.getElementById('speedSlider');
|
||||
const $threadSlider = document.getElementById('threadSlider');
|
||||
|
|
@ -2840,14 +2867,41 @@ $presetSelect.addEventListener('change', function() {
|
|||
|
||||
$customArray.addEventListener('change', function() {
|
||||
if (!isRunning) doReset();
|
||||
updateCustomArrayCount();
|
||||
});
|
||||
|
||||
$customArray.addEventListener('input', function() {
|
||||
updateCustomArrayCount();
|
||||
});
|
||||
|
||||
function updateCustomArrayCount() {
|
||||
const text = $customArray.value.trim();
|
||||
if (!text) {
|
||||
$customArrayCount.textContent = '';
|
||||
return;
|
||||
}
|
||||
const values = text.split(/[,;\s\n\t]+/).filter(function(v) { return v !== '' && !isNaN(parseFloat(v)); });
|
||||
$customArrayCount.textContent = values.length + ' Wert' + (values.length === 1 ? '' : 'e');
|
||||
}
|
||||
|
||||
$btnClearCustom.addEventListener('click', function() {
|
||||
$customArray.value = '';
|
||||
$customArrayCount.textContent = '';
|
||||
$sizeSlider.disabled = false;
|
||||
if (!isRunning) doReset();
|
||||
});
|
||||
|
||||
$btnPasteCustom.addEventListener('click', async function() {
|
||||
try {
|
||||
const text = await navigator.clipboard.readText();
|
||||
$customArray.value = text.replace(/[\r\n]+/g, ', ').replace(/,/g, ', ');
|
||||
updateCustomArrayCount();
|
||||
$customArray.dispatchEvent(new Event('change'));
|
||||
} catch (e) {
|
||||
// Clipboard API not available or permission denied
|
||||
}
|
||||
});
|
||||
|
||||
$btnTheme.addEventListener('click', function() {
|
||||
const isDark = document.documentElement.classList.contains('dark');
|
||||
const newTheme = !isDark;
|
||||
|
|
@ -2922,6 +2976,49 @@ makeTouchSlider($sizeSlider);
|
|||
makeTouchSlider($speedSlider);
|
||||
makeTouchSlider($threadSlider);
|
||||
|
||||
// ================================================================
|
||||
// Slider Tooltip on Hover
|
||||
// ================================================================
|
||||
|
||||
const $sliderTooltip = document.getElementById('sliderTooltip');
|
||||
const $allSliders = [$sizeSlider, $speedSlider, $threadSlider].filter(Boolean);
|
||||
|
||||
$allSliders.forEach(function(slider) {
|
||||
slider.addEventListener('mouseenter', function() {
|
||||
updateSliderTooltip(slider);
|
||||
$sliderTooltip.classList.add('visible');
|
||||
});
|
||||
slider.addEventListener('mousemove', function(e) {
|
||||
updateSliderTooltipPosition(e.clientX, e.clientY);
|
||||
});
|
||||
slider.addEventListener('mouseleave', function() {
|
||||
$sliderTooltip.classList.remove('visible');
|
||||
});
|
||||
});
|
||||
|
||||
function updateSliderTooltip(slider) {
|
||||
if (slider.id === 'sizeSlider') {
|
||||
$sliderTooltip.textContent = slider.value + ' Elemente';
|
||||
} else if (slider.id === 'speedSlider') {
|
||||
const ms = Math.round(1000 * Math.pow(0.001, (parseInt(slider.value) - 1) / 99));
|
||||
$sliderTooltip.textContent = ms + ' ms/Schritt';
|
||||
} else if (slider.id === 'threadSlider') {
|
||||
$sliderTooltip.textContent = slider.value + ' Thread(s)';
|
||||
}
|
||||
}
|
||||
|
||||
function updateSliderTooltipPosition(x, y) {
|
||||
const tw = $sliderTooltip.offsetWidth;
|
||||
const th = $sliderTooltip.offsetHeight;
|
||||
let left = x - tw / 2;
|
||||
let top = y - th - 12;
|
||||
if (left < 8) left = 8;
|
||||
if (left + tw > window.innerWidth - 8) left = window.innerWidth - tw - 8;
|
||||
if (top < 8) top = y + 16;
|
||||
$sliderTooltip.style.left = left + 'px';
|
||||
$sliderTooltip.style.top = top + 'px';
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// URL State Persistence
|
||||
// ================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue