JQuery для начинающих. Часть 6. События

Материал из support.qbpro.ru

Прежде чем приступить к прочтению данной статьи, стоит определиться, что из себя представляют события — для 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 — вывод курсора из элемента

Опробовать события можно на примере с событиями мышки и элементами формы. Большинство из перечисленных событий можно имитировать непосредственно из самого скрипта:

<script lang="javascript"> $('#menu li').click(); </script>


Триггеры

Для работы с триггерами в jQuery предопределены следующие функции:

  • bind (type, data, fnc) — добавляет обработчик событий
  • one (type, data, fnc) — добавляет обработчик событий, который сработает лишь раз
  • trigger (event, data) — вызывает обработчики событий
  • triggerHandler( event, data) — вызывает обработчики событий, без вызова события браузера
  • unbind (type, fnc) — удаляет все обработчики событий с элемента


$('.class').bind('click', function(){
    // что-то делаем
});
// вызываем обработчик
$('.class').trigger('click');
// отключаем обработчик
$('.class').unbind('click');

Можно повесить триггер почти на любой объект:

var obj = {
   test:function() {
       console.log('obj.test');
   }
}
$(obj).bind('someEvent', function(){
  console.log('obj.someEvent');
  this.test();
});
$(obj).trigger('someEvent');

Пространство имен

Обычно, когда мы хотим создать/удалить свой обработчик событий, мы пишем следующий код (чуть выше я об этом уже писал):

// создаем свой обработчик
$('.class').bind('click', function(){
   // что-то делаем
});
// удаляем все обработчики
$('.class').unbind();

Но как всегда, есть ситуации когда нам необходимо отключить не все обработчики (как пример, надо отключить обработку какого-то контрола определенным плагином), в этом случае нам на помощь приходят пространства имен, использовать их достаточно легко:

// создаем обработчик
$('.class').bind('click.namespace', function(){
   // что-то делаем
});
// вызываем обработчик
$('.class').trigger('click.namespace');
// удаляем все обработчики в данном пространстве имен
$('.class').unbind('click.namespace');

Еще примерчик, вешаем обработчик, который выводит текст в консоль.

$('.class').bind('click.namespace', function(){
   console.log('bang');
});
$('.class').trigger('click.namespace'); // вызываем событие, наш обработчик сработает
$('.class').trigger('click');           // тоже работает
$('.class').trigger('click.other');     // событие из другого пространства имен, наш обработчик не будет вызван

Так же, есть поддержка нескольких пространств имен (с версии 1.3, если быть точным):

$('.class').bind('click.a.b', function(){
   // для пространств a и b
});
$('.class').trigger('click.a'); // вызываем обработчик из пространства a
$('.class').unbind('click.b');  // отменяем обработчик для пространства b

Можно одним махом удалить все обработчики с определенного пространства имен:

$('.class').bind('click.namespace', function(){}); // обработчик клика
$('.class').bind('blur.namespace', function(){});  // обработчик фокус
$('.class').unbind('.namespace'); // передумали, и все отменили

Пример использование триггеров и пространства имен Официальная документация по пространствам имен

Работа с live

Очень часто при генерации страниц AJAX’ом возникает необходимость повесить обработчики событий на новые элементы в DOMе, для этой цели служит метод live (первый параметр — имя события, второй — обработчик).

Приведу пример — есть следующая задача:

все внутренние ссылки на страницы должны подгружать контент AJAXом в элемент с id=content

правило №1 верно для ссылок из подгруженного контента

Реализовать первое требование достаточно просто:

$('a[href^=/]').click(function(event){
   $('#content').load($(this).attr('href'));
   return false; // эквивалентно вызову event.preventDefault(); и event.stopPropagation();
});

Выполнить второе правило тоже легко, достаточно слегка модифицировать предыдущий пример:

$('a[href^=/]').live('click', function(event){
   $('#content').load($(this).attr('href'));
   event.preventDefault(); // отменяем действие по умолчанию, но не трогаем bubbling - чтобы не мешать другим обработчикам 
});

Поддерживаемые события: click, dblclick, mousedown, mouseup, mousemove, mouseover, mouseout, keydown, keypress, keyup, change, submit, focusin, focusout, mouseenter, mouseleave

Нет поддержки: blur, focus, change, submit

В противовес функции live существует функция die — она убирает отслеживание событий для вновь появившихся элементов.

Хотелось бы отдельно остановиться на принципе работы метода live — данный метод работает благодаря т.н. «всплытию» событий в DOMе — т.е. когда вы кликаете на любом элементе на странице, то в первую очередь событие сработает на этом элементе, если обработчика события нет, или он не говорит, что дальше «всплывать» не надо (сказать он это может так event.stopPropagation()), то событие идет вверх по DOM дереву и инициализирует обработчики у родительского элемента, и так далее пока не достигнет корня — document’a. Таким образом метод live вешает обработчик событий на document, и затем анализирует каждое событие на предмет наличия элементов описанных вами. Это конечно не самый быстрый способ, но его можно ускорить используя метод delegate, его отличие от live только в том, что вы указываете элемент на который вешаете обработчик «live» событий, таким образом пример выше можно записать так:

$('#content').delegate('a[href^=/]', 'click', function(event){
   $('#content').load($(this).attr('href'));
   event.preventDefault();
});

Touch события

Смартфоны с большим сенсорным экраном — это уже не редкость, вот и web-индустрия начинает адаптироваться под пользователей того же iPhone, если же вам понадобилось подобная адаптация, то вам пригодится следующая информация: События в JavaScript’е:

  • touchstart — аналогично mousedown
  • touchmove — mousemove
  • touchend — mouseup
  • touchcancel — аналогии нет

О том как с ними работать, можно подчерпнуть из статей iPhone Touch Events in JavaScript и Touching and Gesturing on the iPhone Если же вернутся к CSS, то для того же iPhone подключение внешнего CSS файла будет выглядеть следующим образом:

<link rel="stylesheet" href="iphone.css" type='text/css' media='only screen and (max-device-width: 480px)' />

Или в самом CSS:

@media only screen and (max-device-width: 480px) {
 .sidebar {
   display: none;
 }
}

Подробнее читайте в статье iPhone Development: 12 Tips To Get You Started