Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Sự kiện Focus (Focus Events) trong JavaScript

Các sự kiện Focus chính

Sự kiệnKích hoạt khiBubbles
focusElement nhận focus❌ Không
blurElement mất focus❌ Không
focusinElement sắp nhận focus✅ Có
focusoutElement sắp mất focus✅ Có

Lưu ý: focus/blur không bubble, nhưng focusin/focusout bubble. Dùng focusin/focusout khi cần delegate event.

Ví dụ: Đổi màu nền khi focus

<!DOCTYPE html>
<html lang="vi">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Focus Events</title>
    <style>
        body { font-family: 'Segoe UI', sans-serif; padding: 20px; }
        input { display: block; margin: 10px 0; padding: 12px; width: 300px; border: 2px solid #ddd; border-radius: 6px; font-size: 16px; transition: all 0.2s; }
        input:focus { border-color: #1976d2; box-shadow: 0 0 0 3px rgba(25,118,210,0.1); outline: none; }
        .hint { color: #666; font-size: 14px; }
    </style>
</head>
<body>
    <h1>Focus Events trong JavaScript</h1>
    <form id="form">
        <input type="text" placeholder="Username" autocomplete="username">
        <input type="password" class="passW" placeholder="Password" autocomplete="current-password">
    </form>
    <p class="hint">Focus vào ô Password để thấy background đổi màu xanh nhạt</p>

    <script>
        const passEle = document.querySelector('.passW');

        // focus: không bubble - gắn trực tiếp trên element
        passEle.addEventListener('focus', () => {
            passEle.style.backgroundColor = '#e8f5e9'; // Xanh nhạt
        });

        // blur: khi mất focus
        passEle.addEventListener('blur', () => {
            passEle.style.backgroundColor = ''; // Reset về mặc định
        });

        // Demo focusin/focusout (bubble) - gắn trên form cha
        document.getElementById('form').addEventListener('focusin', (e) => {
            console.log('focusin:', e.target.tagName, e.target.type);
        });
        
        document.getElementById('form').addEventListener('focusout', (e) => {
            console.log('focusout:', e.target.tagName);
        });
    </script>
</body>
</html>

Kết quả

Khi click vào ô Password: background chuyển sang xanh nhạt.
Khi click ra ngoài: background trở về trắng.

Ứng dụng thực tế

1. Validation khi blur (mất focus)

emailInput.addEventListener('blur', () => {
    if (emailInput.value && !emailInput.validity.valid) {
        showError(emailInput, 'Email không hợp lệ');
    }
});

2. Floating Label Pattern

input.addEventListener('focus', () => label.classList.add('active'));
input.addEventListener('blur', () => {
    if (!input.value) label.classList.remove('active');
});

3. Trap Focus trong Modal (Accessibility)

function trapFocus(modal) {
    const focusable = modal.querySelectorAll('button, input, select, textarea, a[href], [tabindex]:not([tabindex="-1"])');
    const first = focusable[0];
    const last = focusable[focusable.length - 1];
    
    modal.addEventListener('keydown', (e) => {
        if (e.key !== 'Tab') return;
        if (e.shiftKey && document.activeElement === first) {
            e.preventDefault(); last.focus();
        } else if (!e.shiftKey && document.activeElement === last) {
            e.preventDefault(); first.focus();
        }
    });
    
    first.focus(); // Auto-focus khi mở
}

4. document.activeElement

// Kiểm tra element nào đang focus
console.log(document.activeElement);

// Kiểm tra có element nào focus không
if (document.activeElement === document.body) {
    console.log('Không có element nào focus');
}