Обработка событий браузера в JavaScript, вероятно, является наиболее трудоемким, разочаровывающим и неправильно понятым аспектом программирования на стороне клиента. Такие библиотеки, как jQuery, облегчают эту задачу, но все же полезно немного узнать о том, что происходит под поверхностью.
В этой статье мы реализуем задержку события, т.е. ответ на событие будет происходить через некоторое время после его запуска. Это часто полезно в таких ситуациях, как создание раскрывающихся меню. Итак, давайте начнем с небольшого кода HTML и CSS (он краткий для целей данного примера, следовательно, без DOCTYPE)…
<html> <head> <title>Latency test</title> <style type="text/css"> #element1 { width: 20em; margin: 20px; background-color: #dff; border: 2px solid #00d; } #para1 { text-align: center; padding: 10px; margin: 30px; background-color: #ccc; border: 1px solid #000; } </style> </head> <body> <div id="element1"> <p id="para1">Hover over me...</p> </div> </body> </html>
Это просто производит коробку, похожую на следующую …
Теперь мы добавим немного JavaScript прямо перед закрывающим тегом body
…
<script type="text/javascript"> window.onload = function() { // get nodes var element1 = document.getElementById("element1"); var para1 = document.getElementById("para1"); // define events if (element1 && para1) { element1.onmouseover = Handler; element1.onmouseout = Handler; } // event handler function Handler(e) { e = (e ? e : window.event); var on = (e.type == "mouseover"); Highlight(on); return false; } // highlight or dim element (pass true|false) function Highlight(on) { para1.firstChild.nodeValue = (on ? "over" : "out"); element1.style.backgroundColor = (on ? "#ffd" : "#dff"); if (!on) alert("moved out"); } }; </script>
Это добавляет пару событий (DOM0), которые срабатывают, когда курсор перемещается над или из светло-голубого элемента element1 div
. Функция обработчика событий вызывается для того, чтобы разобраться в несоответствиях IE и выяснить, было ли запущено событие мыши над или вне. Функция Highlight передается true (при наведении курсора мыши) или false (при отсутствии мыши) и соответственно изменяет текст абзаца и цвет фона. Наконец, если мышь выдвигается, отображается окно с предупреждением.
Сценарий работает, однако, когда мы перемещаем мышь в серое поле с абзацем, появляется предупреждение «перемещен». Это происходит потому, что браузер запускает два события — mouseout для element1 и mouseover для para1. Хотя мы не делегировали обработчик событий для para1, браузеры реализуют технику, известную как пузыривание, и события будут распространяться через всех потомков element1.
В этом примере мы заботимся только о том, чтобы последним сработавшим событием была указатель мыши, за которым сразу не последовало наведение мыши. Поэтому мы можем исправить проблему в нашей функции Handler () с небольшой задержкой события:
var timer; function Handler(e) { e = (e ? e : window.event); var on = (e.type == "mouseover"); if (timer) clearTimeout(timer); timer = setTimeout( function() { Highlight(on); }, 300); return false; }
Когда происходит событие, мы очищаем любой существующий тайм-аут. Затем создается новый тайм-аут, который вызывает функцию Highlight через 300 миллисекунд (Highlight (on) содержится в функции, поэтому значение «on» сохраняется замыканием). Этот процесс делает невозможным выполнение Highlight () чаще, чем каждые 300 миллисекунд. Когда он вызывается, доступно только самое последнее значение «on».
Перезагрузите страницу, и вы заметите, что перед анимацией какого-либо события происходит небольшая задержка. Кроме того, предупреждение появится только при выходе за пределы синего поля # element1.
Я надеюсь, что вы найдете эту технику полезной в других проектах JavaScript.