// Mobile Touch Tooltip System
class MobileTooltip {
constructor() {
this.tooltip = null;
this.longPressTimer = null;
this.longPressDuration = 600; // 600ms for long press
this.isLongPressing = false;
this.init();
}
init() {
// Create tooltip element
this.tooltip = document.createElement('div');
this.tooltip.className = 'mobile-tooltip';
document.body.appendChild(this.tooltip);
// Add touch event listeners to all elements with title attribute
document.querySelectorAll('[title]').forEach(element => {
this.addTouchListeners(element);
});
// Hide tooltip when touching elsewhere
document.addEventListener('touchstart', (e) => {
if (!e.target.closest('[title]')) {
this.hideTooltip();
}
});
}
addTouchListeners(element) {
let startX, startY;
element.addEventListener('touchstart', (e) => {
// Store initial touch position
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
// Add visual feedback
element.classList.add('long-press-active');
// Start long press timer
this.longPressTimer = setTimeout(() => {
this.isLongPressing = true;
this.showTooltip(element, e.touches[0]);
// Add haptic feedback if available
if (navigator.vibrate) {
navigator.vibrate(50);
}
}, this.longPressDuration);
});
element.addEventListener('touchmove', (e) => {
// Cancel long press if finger moves too much
const currentX = e.touches[0].clientX;
const currentY = e.touches[0].clientY;
const deltaX = Math.abs(currentX - startX);
const deltaY = Math.abs(currentY - startY);
if (deltaX > 15 || deltaY > 15) {
this.cancelLongPress(element);
}
});
element.addEventListener('touchend', () => {
this.cancelLongPress(element);
// If it was a long press, prevent default behavior
if (this.isLongPressing) {
setTimeout(() => {
this.isLongPressing = false;
}, 100);
}
});
element.addEventListener('touchcancel', () => {
this.cancelLongPress(element);
});
}
cancelLongPress(element) {
if (this.longPressTimer) {
clearTimeout(this.longPressTimer);
this.longPressTimer = null;
}
element.classList.remove('long-press-active');
}
showTooltip(element, touch) {
const titleText = element.getAttribute('title');
if (!titleText) return;
// Set tooltip content
this.tooltip.textContent = titleText;
// Position tooltip
const rect = element.getBoundingClientRect();
// Calculate position (above the element, centered)
let left = rect.left + (rect.width / 2) - (140); // Center tooltip
let top = rect.top - 60; // Position above the element
// Keep tooltip within viewport
const padding = 10;
if (left < padding) left = padding;
if (left + 280 > window.innerWidth - padding) {
left = window.innerWidth - 280 - padding;
}
if (top < padding) {
top = rect.bottom + 10; // Show below if no space above
}
this.tooltip.style.left = left + 'px';
this.tooltip.style.top = top + 'px';
// Show tooltip
this.tooltip.classList.add('show');
}
hideTooltip() {
this.tooltip.classList.remove('show');
}
}
// Initialize mobile tooltip system
if ('ontouchstart' in window || navigator.maxTouchPoints > 0) {
document.addEventListener('DOMContentLoaded', function() {
new MobileTooltip();
});
}