События
Прежде чем приступить к прочтению данной главы, стоит определиться, что же из себя представляют события web-страницы. Так вот – события – это любые действия пользователя, будь то ввод данных с клавиатуры, проматывание страницы или передвижения мышки, и конечно же "клики".
А ещё существуют события создаваемые скриптами, и их обработчики – триггеры и хэндлеры, но о них чуть позже.
jQuery работает практически со всеми событиями в JavaScript'е, приведу список оных с небольшими пояснениями:
change — изменение значения элемента (значение, при потери фокуса, элемента отличается от изначального, при получении фокуса)
click — клик по элементу (порядок событий: "mousedown", "mouseup", "click")
dblclick — двойной щелчок мышки
resize — изменение размеров элементов
scroll — скроллинг элемента
select — выбор текста (только для "input[type=text]" и "textarea")
submit — отправка формы
focus — фокус на элементе - актуально для "input[type=text]", но в современных браузерах работает и с другими элементами
blur — фокус ушёл с элемента — актуально для "input[type=text]" — срабатывает при клике по другому элементу на странице или по событию клавиатуры (к примеру переключение по tab'у)
focusin — фокус на элементе, данное событие срабатывает на предке элемента, для которого произошло событие "focus"
focusout — фокус ушёл с элемента, данное событие срабатывает на предке элемента, для которого произошло событие "blur"
keydown — нажатие клавиши на клавиатуре
keypress — нажатие клавиши на клавиатуре (keydown ? keypress ? keyup)
keyup — отжатие клавиши на клавиатуре
load — загрузка элемента (например <img>)
unload — выгрузка элемента (например "window")
mousedown — нажатие клавиши мыши
mouseup — отжатие клавиши мыши
mousemove — движение курсора
mouseenter — наведение курсора на элемент, не срабатывает при переходе фокуса на дочерние элементы
mouseleave — вывод курсора из элемента, не срабатывает при переходе фокуса на дочерние элементы
mouseover — наведение курсора на элемент
mouseout — вывод курсора из элемента
Опробовать события можно на примере с событиями мышки и элементами формы. Для большинства событий существуют "shorthand" методы, так для отслеживания "click" можно использовать "click()" :)
Вызов большинства из перечисленных событий можно эмулировать непосредственно из самого скрипта:
<script>
$("#menu li a").click()
// или используя метод trigger $("#menu li a").trigger("click")
</script>
Теперь стоит рассказать немного и об обработчиках событий, для примера возьму код строкой выше, и слегка его модифицирую:
$("#menu li a").click(function(event){
alert("Hello!")
})
Теперь кликнув по ссылке вы увидите приветствие и после закрытия оного браузер перейдет по ссылке указанной в атрибуте "href". Но это не совсем то, что мне хотелось – надо было лишь вывести текст, и никуда не уходить. Ага, для этого стоит отменить действие по умолчанию:
$("#menu li a").click(function(event){
alert("Hello!");
event.preventDefault();
})
Теперь перехода нет, т.к. метод "preventDefault()" предотвращает данное действие. Но вот если кто-то повесит обработчик на само меню?
$("#menu").click(function(event){
alert("Menu!");
})
В результате мы получим два сообщения, но почему? Если у вас возникает подобный вопрос, значит вы еще не знакомы с тем, как обрабатываются события. Попробую кратенько дать вводную, когда вы кликаете на элементе в DOM дереве, то происходит "погружение" события – т.е. вначале все родительские элементы могут обработать "клик", и лишь потом он доберётся до элемента по которому был совершён, но и это еще не всё, затем событие начинает проделывать обратный путь – "всплывает", давая тем самым второй шанс родительским элементам обработать событие.
Но не так всё гладко, у нас же есть IE, который принципиально не работает с "погружением", поэтому все решили идти по пути наименьшего сопротивления и обрабатывают события лишь на этапе "всплытия".
Рекомендую к прочтению "Порядок срабатывание событий" из учебника Ильи Кантора
Хорошо, вроде бы понятно, теперь вернёмся к нашему примеру, и пытаемся понять что же у нас происходит – у нас есть обработчик клика для ссылки и непосредственно для самого меню, в котором эта ссылка находится. Теперь кликая по ссылке, срабатывает обработчик события на ссылке, и затем событие всплывает до меню, и срабатывает его обработчик события "click". Но это не совсем желаемый результат, и для борьбы с подобным вредительством, необходимо останавливать "всплытие" событий:
$("#menu li a").click(function(event){
alert("Hello!");
event.preventDefault();
event.stopPropagation();
})Для ускорения разработки в jQuery есть быстрый способ вызова этих двух методов за раз:
$("#menu li a").click(function(event){
return false; // вот это он :)
})Теперь у вас есть достаточный багаж знаний, чтобы легко манипулировать событиями на странице. Хотя я добавлю еще немного — для того, чтобы сработал лишь ваш обработчик события, можно использовать метод "stopImmediatePropagation()":
$("#menu li a").click(function(event){
alert("Hello!");
event.stopImmediatePropagation();
return false;
})
$("#menu li a").click(function(event){
alert("Hello again!");
return false;
})В данном примере, при клике по ссылке будет выведено лишь одно сообщение. И да, порядок имеет значение.
Учимся рулить
Мы уже успели познакомиться с методом "click()", в действительности этот метод представляет из себя обёртку для вызова "on()" и "trigger()":
if (arguments.length > 0) {
this.on("click", null, data, fn ) :
} else {
this.trigger("click");
}Ой, код я чуть-чуть изменил — для читаемости, если же любопытство восторжествует, то ищите в исходном коде по строке "dblclick"
Ну так давайте же попробуем без этих обёрток:
// вешаем обработчик
$('.class').on('click', function(){
// что-то делаем
});
// вызываем обработчик
$('.class').trigger('click');
// отключаем обработчик
$('.class').unbind('click');Можно повесить обработчик событий практически на любой объект:
// проще некуда
var obj = {
test:function() {
console.log('obj.test');
}
}
// создаём обработчик произвольного события someEvent
$(obj).on('someEvent', function(){
console.log('obj.someEvent');
this.test();
});
// инициируем событие someEvent
$(obj).trigger('someEvent');
// полюбопытствуем
console.log(obj);Скопируйте приведенный код в консоль и запустите, я думаю вам будет интересно ;)
Пространство имен
Как вы уже узнали, когда мы хотим создать/удалить свой обработчик событий, мы пишем следующий код:
// создаем свой обработчик
$('.class').on('click', function(){
// что-то делаем
});
// удаляем все обработчики
$('.class').unbind();Но как всегда, есть ситуации когда нам необходимо отключить не все обработчики (как пример, надо отключить обработку какого-то контрола определенным плагином), в этом случае нам на помощь приходят пространства имен, использовать их достаточно легко:
// создаём обработчик
$('.class').on('click.namespace', function(){
// что-то делаем
});
// вызываем обработчик
$('.class').trigger('click.namespace');
// вызываем все обработчики без пространства имён
$('.class').trigger('click!');
// удаляем все обработчики click в данном пространстве имён
$('.class').unbind('click.namespace');Еще примерчик, вешаем обработчик, который выводит текст в консоль:
$('.class').on('click.namespace', function(){
console.log('bang');
});
// вызываем событие, наш обработчик сработает
$('.class').trigger('click.namespace');
// тоже работает
$('.class').trigger('click');
// событие из другого пространства имён, наш обработчик не будет вызван
$('.class').trigger('click.other');Также, есть поддержка нескольких пространств имён:
$('.class').on('click.a.b', function(){
// для пространства имён a и b
});
// вызываем обработчик из пространства a
$('.class').trigger('click.a');
// отменяем обработчик click для пространства b
$('.class').unbind('click.b');Можно одним махом удалить все обработчики с определенного пространства имен:
// обработчик клика
$('.class').on('click.namespace', function(){});
// обработчик фокус
$('.class').on('blur.namespace', function(){});
// передумали, и все отменили
$('.class').unbind('.namespace');Официальная документация скудна на этот счёт, и я надеюсь мой пример поможет лучше разобраться в данном вопросе.
<!DOCTYPE html>
<html dir="ltr" lang="en-US">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>События и пространства имён</title>
<link rel="profile" href="http://gmpg.org/xfn/11"/>
<link rel="shortcut icon" href="http://anton.shevchuk.name/favicon.ico"/>
<link rel="stylesheet" href="css/styles.css"/>
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/code.js"></script>
<script type="text/javascript">
$(function(){
$('#myButton').click(function(event){
return false;
});
});
</script>
<style>
article ul {
margin: 20px;
float:left;
list-style: none
}
article a {
display: block;
padding: 4px 8px;
border:1px solid #456;
border-radius: 2px;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
}
</style>
</head>
<body>
<div id="content" class="wrapper box">
<div id="output">
<h3>Output</h3>
<pre></pre>
</div>
<menu label="Try...">
<a href="events.form.html" title="go prev" class="button alignleft" rel="prev">? Prev </a>
<a href="index.html" title="back to Index" class="button alignleft" rel="index">Index §</a>
<a href="#" title="reload" class="button alignleft" onclick="window.location.reload();return false">Reload ¤</a>
<hr/>
<pre><code>$(<span>'#myButton'</span>).on(<span>'click'</span>, function(){
appendOut(<span>"click\n"</span>); })</code></pre>
<button type="button" class="code">Run Code</button>
<pre><code>$(<span>'#myButton'</span>).on(<span>'click.space'</span>, function(){
appendOut(<span>"click.space\n"</span>); })</code></pre>
<button type="button" class="code">Run Code</button>
<pre><code>$(<span>'#myButton'</span>).on(<span>'click.my'</span>, function(){
appendOut(<span>"click.my\n"</span>); })</code></pre>
<button type="button" class="code">Run Code</button>
<pre><code>$(<span>'#myButton'</span>).on(<span>'click.my.space'</span>, function(){
appendOut(<span>"click.my.space\n"</span>); })</code></pre>
<button type="button" class="code">Run Code</button>
<pre><code>$(<span>'#myButton'</span>).trigger(<span>'click'</span>)</code></pre>
<button type="button" class="code">Run Code</button>
<pre><code>$(<span>'#myButton'</span>).trigger(<span>'click!'</span>)</code></pre>
<button type="button" class="code">Run Code</button>
<pre><code>$(<span>'#myButton'</span>).trigger(<span>'click.my!'</span>)</code></pre>
<button type="button" class="code">Run Code</button>
<pre><code>$(<span>'#myButton'</span>).off(<span>'.space'</span>)</code></pre>
<button type="button" class="code">Run Code</button>
</menu>
<header>
<h1>Работа с пространством имён</h1>
<h2>Это уже круто знать и использовать</h2>
</header>
<article>
<a href="#" id="myButton" class="button">#myButton</a>
</article>
<footer>
©copyright 2014 Anton Shevchuk — <a href="http://anton.shevchuk.name/jquery-book/">jQuery Book</a>
</footer>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-1669896-2']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</div>
</body>
</html>