19. Библиотека jQuery

В языке JavaScript чрезвычайно простой базовый и весьма сложный клиентский API, который к тому же отягощен многочисленными несовместимостями между браузерами. С выходом IE9 исчезли самые неприятные несовместимости, но многие программисты считают, что веб-приложения удобнее писать с использованием фреймворков или вспомогательных библиотек на языке JavaScript, упрощающих решение типичных задач и скрывающих различия между браузерами. На момент написания этих строк одной из наиболее популярных и широко используемых была библиотека jQuery.

В число широко используемых входят также не описываемые в этой книге библиотеки Prototype, YUI и dojo. Еще большее количество библиотек можно отыскать в Интернете, выполнив поиск по фразе «JavaScript libraries».

Библиотека jQuery получила весьма широкое распространение, и поэтому веб-разработчики должны быть знакомы с ней: даже если вы не собираетесь ее использовать, вы наверняка встретитесь с ней в сценариях, написанных другими. К счастью, библиотека jQuery весьма стабильна и достаточно мала, чтобы ее можно было описать в этой книге. В этой главе дается обстоятельное введение, а в четвертой части вы найдете краткий справочник по библиотеке jQuery. В справочнике отсутствуют отдельные статьи для методов из библиотеки jQuery, однако в статье jQuery даются краткие описания всех методов.

Библиотека jQuery упрощает поиск элементов документа и облегчает манипулирование ими: добавление содержимого, изменение HTML-атрибутов и CSS-свойств, определение обработчиков событий и воспроизведение анимационных эффектов. Она также имеет вспомогательные функции поддержки архитектуры Ajax, позволяющие выполнять динамические HTTP-запросы, и функции общего назначения для работы с объектами и массивами.

Как следует из ее имени, основу библиотеки jQuery составляет реализация механизма запросов. Типичный запрос использует CSS-селектор, идентифицирующий множество элементов документа, и возвращает объект, представляющий эти элементы. Данный возвращаемый объект имеет множество удобных методов для выполнения операций над всей группой выбранных элементов. Всякий раз, когда это возможно, эти методы возвращают объект, относительно которого они вызывались, что позволяет использовать прием составления цепочек из вызовов методов. Ниже перечислены особенности, которые обеспечивают широту возможностей и удобство использования библиотеки jQuery:

Эта Глава начинается с введения в библиотеку jQuery, где будет показано, как выполнять простейшие запросы и как обрабатывать результаты. В последующих разделах описывается:

содержание 19.1. Основы jQuery содержание

Библиотека jQuery определяет единственную глобальную функцию с именем jQuery(). Эта функция используется настолько часто, что библиотека определяет также глобальное имя $, как сокращенный псевдоним этой функции. Эти два имени – все, что библиотека jQuery добавляет в глобальное пространство имен.

Если вы определяете собственное имя $ в своих сценариях или используете другую библиотеку, такую как Prototype, тоже использующую имя $, вы можете вызвать метод jQuery.noConflict(), чтобы восстановить оригинальное значение имени $.

Эта глобальная функция с двумя именами является центральной функцией механизма запросов в библиотеке jQuery. К примеру, можно запросить множество всех элементов <div> в документе так:

var divs = $("div");
Эта функция возвращает множество из нуля или более элементов DOM, которое называется объектом jQuery. Обратите внимание, что jQuery() является фабричной функцией, а не конструктором: она возвращает вновь созданный объект, но используется без ключевого слова new. Объект jQuery определяет множество методов для выполнения операций над множеством элементов, которое он представляет, и большая часть главы будет посвящена описанию этих методов. Ниже приводится пример инструкции, которая отыскивает, выделяет цветом и быстро отображает все скрытые элементы <р>, имеющие класс "details":
$("p.details").css("background-color", "yellow").show("fast");
Метод css() оперирует объектом jQuery, возвращаемым функцией $(), и возвращает этот же объект, благодаря чему метод show() может быть вызван в этой же компактной «цепочке вызовов методов». Этот прием составления цепочек является весьма характерным при использовании библиотеки jQuery. В качестве другого примера демонстрируется инструкция, выполняющая поиск всех элементов, имеющих CSS-класс "clicktohide", и регистрирующая обработчик события в каждом из них. Этот обработчик вызывается, когда пользователь щелкает на элементе и заставляет элемент медленно «выезжать» за границы окна вверх и скрываться:
$(".clicktohide").click(function() { $(this).slideUp("slow"); });

содержание 19.1.1. Функция jQuery()

Функция jQuery() (она же $()) является наиболее важной в библиотеке jQuery. Однако она существенно перегружена и может быть вызвана четырьмя разными способами.

Первый и наиболее типичный способ вызова $() предусматривает передачу ей CSS-селектора (строки). При вызове таким способом она возвращает множество элементов из текущего документа, соответствующих селектору. Библиотека в значительной степени поддерживает синтаксис селекторов CSS3 плюс некоторые собственные расширения. Более подробное описание синтаксиса селекторов jQuery приводится в разделе 19.8.1 . Если во втором аргументе передать функции $() элемент или объект jQuery, она вернет только элементы-потомки указанного элемента или элементов, соответствующие селектору. Этот необязательный второй аргумент определяет начальную точку (или точки) выполнения запроса и часто называется контекстом.

При втором способе вызова функции$() передается объект Element, Document или Window. Подобный вызов просто обертывает элемент, документ или окно объектом jQuery и возвращает его. Это дает возможность манипулировать элементом с помощью методов объекта jQuery вместо низкоуровневых методов модели DOM. Например, в программах, использующих библиотеку jQuery, часто можно встретить вызов $(document) или $(this). Объекты jQuery могут представлять множество элементов документа, а кроме того, функции $() можно передавать массив элементов. В этом случае возвращаемый объект jQuery будет представлять множество элементов, имевшихся в массиве.

Получение библиотеки jQuery

Библиотека jQuery является свободно распространяемым программным обеспечением. Ее можно загрузить с сайта http://jquery.com. Получив библиотеку, вы сможете подключать ее к своим веб-страницам с помощью элемента <script>, как показано ниже:

<script> src= "jquery-1.4.2.min.js" </script>
Слово "min" в имени файла здесь указывает, что используется минимизированная версия библиотеки, из которой были удалены комментарии и лишние пробелы, а внутренние идентификаторы были заменены более короткими именами.

Другой способ задействовать библиотеку jQuery в своих веб-приложениях заключается в использовании сети распространения библиотеки, для чего достаточно указать любой из следующих URL-адресов:
http://code.jquery.com/jquery-1.4.2.min.js
http://ajax.microsoft.eom/ajax/jquery/jquery-1.4.2.min.js
http://ajax.googleapis.eom/ajax/libs/jquery/1.4.2/jquery.min.js

В этой главе описывается библиотека jQuery версии 1.4. Если вы пользуетесь другой версией, замените номер версии «1.4.2» в приведённых URL-адресах на требуемый вам.

На момент написания этой главы текущей версией библиотеки jQuery была 1.4.2. Когда книга готовилась к печати, была выпущена версия jQuery 1.5. Изменения в jQuery 1.5 в основном касаются механизма поддержки архитектуры Ajax и будут упоминаться в разделе 19.6.

Если вы пользуетесь сетью распространения Google CDN, вы можете указать номер версии «1.4», чтобы получить самую свежую версию в ветке 1.4.x, или просто «1», чтобы получить самую свежую версию ниже 2.0. Основное преимущество использования подобных широко известных адресов состоит в том, что благодаря огромной популярности jQuery посетители вашего веб-сайта наверняка будут иметь копию библиотеки в кэше своих браузеров, и веб-приложению не придется тратить дополнительное время на ее загрузку.

При третьем способе вызова функции $() передается строка с разметкой HTML. В этом случае библиотека jQuery создаст HTML-элемент или элементы, определяемые этой разметкой, и вернет представляющий их объект jQuery. Библиотека jQuery не вставляет вновь созданные элементы в документ, но методы объекта jQuery, описываемые в разделе 19.3, позволяют легко вставить их в любое место. Обратите внимание, что таким образом функции $() нельзя передать простой текст, так как в этом случае jQuery решит, что вы передали CSS-селектор. При таком способе вызова строка, передаваемая функции $(), должна включать хотя бы один HTML-тег в угловых скобках.

При вызове третьим способом функция $() может принимать необязательный второй аргумент. В нем можно передать объект Document, чтобы указать документ, с которым должны быть связаны элементы. (Если, к примеру, предполагается, что создаваемые элементы будут вставлены в элемент <iframe>, необходимо явно указать объект документа этого фрейма.) Или передать объект во втором аргументе. В этом случае предполагается, что свойства объекта определяют имена и значения HTML-атрибутов, которые должны быть установлены во вновь созданном элементе. Но если объект будет содержать свойства с такими именами, как "css", "html", "text", "width", "height", "offset", "val" или "data", или свойства с именами, совпадающими с именами методов регистрации обработчиков событий в библиотеке jQuery, она будет вызывать методы с этими именами для вновь созданного элемента и передавать им значения соответствующих свойств. (Методы, такие как css(), html() и text() рассматриваются в разделе 19.2, а методы регистрации обработчиков событий – в разделе 19.4). Например:

var img = $("<img/>", // Создать новый элемент <img>
{ src:url, //с этим HTML-атрибутом,
  css: {borderWidth:5}. // этим CSS-стилем
  click: handleClick // и этим обработчиком события.
});  
Наконец, при четвертом способе вызова функции $() передается функция. В этом случае указанная вами функция будет вызвана, когда документ будет полностью загружен и дерево DOM документа будет готово к выполнению операций. Это версия функции onload(), представленной в примере 13.5, реализованная в библиотеке jQuery. Очень часто можно встретить jQuery-программы, реализованные в виде анонимных функций, объявляемых в вызове функции jQuery():
jQuery(function() { // Будет вызвана по окончании загрузки документа;
// Здесь находится весь программный код, использующий jQuery
});  
Иногда можно увидеть вызов $(f), оформленный в старом и более явном стиле:
$(document).ready(f).

Функция, передаваемая jQuery(), будет вызвана со ссылкой this, указывающей на объект document, и функцией jQuery в качестве единственного аргумента. Это означает, что вы можете удалить глобальное определение функции $ и по-прежнему использовать этот удобный псевдоним локально, как показано ниже:

jQuery.noConflict() // Восстановить оригинальное значение $
jQuery(function($) { // Использовать $ как локальный псевдоним функции jQuery
// Здесь размещаете весь программный код, использующий jQuery
});
Функции, зарегистрированные с помощью $(), будут вызваны библиотекой jQuery, когда будет возбуждено событие "DOMContentLoaded" (раздел 13.3.4) или, если это событие не поддерживается, когда будет возбуждено событие "load". To есть когда документ будет загружен и полностью разобран, но внешние ресурсы, такие как изображения, еще могут быть не загружены. Если функцию передать в вызов $() после того, как дерево DOM будет готово, она будет вызвана немедленно, перед тем как $() вернет управление.

Кроме того, библиотека jQuery использует функцию jQuery() как собственное пространство имен и определяет в нем множество вспомогательных функций и свойств. Одной из таких вспомогательных функций является функция jQuery.noConflict(), упоминавшаяся выше. В числе других функций общего назначения можно назвать функцию jQuery.each(), предназначенную для выполнения итераций, jQuery.parseJSON() – для синтаксического анализа данных в формате JSON. Перечень вспомогательных функций общего назначения приводится в разделе 19.7, а другие вспомогательные функции из библиотеки jQuery описываются на протяжении всей главы.

Терминология jQuery

Давайте остановимся, чтобы определить некоторые важные термины, которые будут встречаться на протяжении этой главы:

«Функция jQuery»

Функция jQuery – это значение jQuery или $. Эта функция создает объекты jQuery, регистрирует обработчики, которые вызываются, когда дерево DOM будет готово к выполнению операций, а также служит пространством имен библиотеки jQuery. Я обычно использую имя $(). Поскольку она служит пространством имен, функция jQuery может также называться «глобальным объектом jQuery», но очень важно не путать ее с «объектом jQuery».

«Объект jQuery»

Объект jQuery – это объект, возвращаемый функцией jQuery. Объект jQuery представляет множество элементов документа и может также называться «результатом функции jQuery», «множеством jQuery» или «обернутым набором».

«выбранные элементы»

Когда функции jQuery передается CSS-селектор, она возвращает объект jQuery, представляющий множество элементов документа, соответствующих этому селектору. При описании методов объекта jQuery я часто буду употреблять фразу «выбранные элементы», ссылаясь на элементы множества. Например, при описании метода attr() я мог бы сказать: «метод attr() устанавливает HTML-атрибуты выбранных элементов» вместо более точной, но трудно читаемой фразы: «метод attr() устанавливает HTML-атрибуты элементов в объекте jQuery, относительно которого он был вызван». Обратите внимание, что слово «выбранных» относится к CSS-селектору и не имеет никакого отношения к элементам, выбираемым пользователем.

«функция библиотеки jQuery»

Функция библиотеки jQuery – это функция, такая как jQuery.noConflict(), которая определена в пространстве имен функции jQuery. Функции библиотеки jQuery могут также упоминаться как «статические методы».

«метод jQuery»

Метод jQuery – это метод объекта jQuery, возвращаемого функцией jQuery. Наиболее важной частью библиотеки jQuery являются мощные методы, которые она определяет.

Иногда сложно уловить различия между методами объекта jQuery и функциями библиотеки jQuery, потому что многие методы и функции имеют одинаковые имена. Обратите внимание, что следующие две строки программного кода выполняют разные операции:

// Вызвать функцию each() библиотеки jQuery, чтобы вызвать функцию f
// для каждого элемента массива a
$.each(a,f);
// Вызвать функцию jQuery(), чтобы получить объект jQuery, представляющий
// все элементы <а> в документе. Затем вызвать метод $.each() этого объекта jQuery,
// чтобы вызвать функцию f для каждого выбранного элемента.
$("a").each(f);

В официальной документации по библиотеке jQuery, которую можно найти на сайте http://jquery.com, такие имена, как $.each, используются для ссылки на функции библиотеки jQuery, а такие имена, как .each (с точкой, но без знака доллара), – для ссылки на методы объекта jQuery. Вместо них в этой книге я буду использовать термины «функция» и «метод». Что именно подразумевается, обычно будет достаточно очевидно из контекста обсуждения.

содержание 19.1.2. Запросы и результаты запросов

Когда функции $() передается CSS-селектор, она возвращает объект jQuery, представляющий множество («выбранных») элементов, соответствующих селектору. С CSS-селекторами мы познакомились в разделе 15.2.5, куда вы можете вернуться, чтобы освежить память, – все примеры селекторов, представленные там, могут передаваться функции $(). Конкретный синтаксис селекторов, поддерживаемый библиотекой jQuery, подробно будет рассматриваться в разделе 19.8.1. Однако, прежде чем углубиться в особенности синтаксиса селекторов, мы сначала разберемся с тем, что можно делать с результатами запроса.

Возвращаемым значением функции $() является объект jQuery. Объекты jQuery – это объекты, подобные массивам: они имеют свойство length и свойства с числовыми именами, начиная с 0 до length-1. (Подробнее об объектах, подобных массивам, рассказывается в разделе 7.11.) Это означает, что к содержимому объекта jQuery можно обращаться, используя стандартный синтаксис обращения к элементам массива с квадратными скобками:

// To же самое, что document.body
$(""body").length // => 1: документ имеет единственный элемент body
$("body")[0]
Если при работе с объектом jQuery вы предпочитаете не использовать синтаксис массивов, вместо свойства length можно использовать метод size(), а вместо индексов в квадратных скобках – метод get(). Если потребуется преобразовать объект jQuery в настоящий массив, можно вызвать метод toArray(). В дополнение к свойству length объекты jQuery имеют еще три свойства, представляющие определенный интерес. Свойство selector хранит строку селектора (если таковая имеется), которая использовалась при создании объекта jQuery. Свойство context ссылается на объект контекста, который был передан функции $() во втором аргументе, в противном случае оно будет ссылаться на объект Document. Наконец, все объекты jQuery имеют свойство jquery, проверка наличия которого является самым простым способом отличить объект jQuery от любого другого объекта, подобного массиву. Значением свойства jquery является строка с номером версии библиотеки jQuery:
// Отыскать все элементы <script> в теле документа
var bodyscripts = $("script", document.body);
bodyscripts.selector // => "script"
bodyscripts.context // => document.body
bodyscripts.jquery // => "1.4.2"

Если потребуется обойти в цикле все элементы в объекте jQuery, вместо цикла for можно использовать метод each(). Метод each() напоминает метод forEach() массивов, определяемый стандартом ECMAScript 5 (ES5). В единственном аргументе он принимает функцию обратного вызова, которая будет вызвана для каждого элемента в объекте jQuery (в порядке следования в документе). Эта функция вызывается как метод элемента, т.е. внутри функции ключевое слово this ссылается на объект Element. Кроме того, метод each() передает функции обратного вызова индекс и элемент в первом и втором аргументах. Обратите внимание, что ссылка this и второй аргумент ссылаются на обычные элементы документа, а не на объекты jQuery. Если для работы с элементом внутри функции потребуется использовать методы объекта jQuery, передайте этот элемент функции $(). Метод each() объекта jQuery имеет одну особенность, которая существенно отличает его от метода forEach(): если функция обратного вызова вернет false для какого-либо элемента, итерации будут остановлены после этого элемента (это напоминает использование ключевого слова break в обычном цикле). Метод each() возвращает объект jQuery, относительно которого он был вызван, благодаря чему он может использоваться в цепочках вызовов методов. Например (здесь используется метод prepend(), который будет описан в разделе 19.3):

// Пронумеровать элементы div документа вплоть до элемента div#last (включительно)
$('div").each(function(idx) { // отыскать все элементы <div> и обойти их
  $(this).prepend(idx + ":"); // Вставить индекс в начало каждого
  if (this, id === "last") return false; // Остановиться по достижении
}); // элемента #last
Несмотря на широту возможностей, метод each() не слишком часто используется на практике, поскольку методы объекта jQuery обычно неявно выполняют итерации по всем выбранным элементам и выполняют операции над ними всеми. Надобность в методе each() обычно возникает только в случае, когда необходимо обработать выбранные элементы каким-то другим способом. Но даже в этом случае необходимость в методе each() может отсутствовать, поскольку многие методы объекта jQuery позволяют передавать функцию обратного вызова.

Библиотека jQuery поддерживает методы массивов, определяемые стандартом ES5, и содержит пару методов, по своей функциональности похожих на методы в стандарте ES5. Метод map() объекта jQuery действует практически так же, как метод Array.map(). Он принимает функцию обратного вызова в виде аргумента и вызывает ее для каждого элемента в объекте jQuery, собирая значения, возвращаемые этой функцией, и возвращая новый объект jQuery, хранящий эти значения. Метод map() вызывает функцию точно так же, как это делает метод each(): он передает ей элемент в виде ссылки this и во втором аргументе, а в первом аргументе – индекс элемента. Если функция обратного вызова вернет null или undefined, это значение будет проигнорировано и не будет добавлено в новый объект jQuery. Если функция обратного вызова вернет массив или объект, подобный массиву (такой как объект jQuery), этот объект будет «развернут» и содержащиеся в нем элементы по отдельности будут добавлены в новый объект jQuery. Обратите внимание, что объект jQuery, возвращаемый методом map(), может хранить объекты, не являющиеся элементами документа, но он по-прежнему будет действовать как объект, подобный массиву. Например:

// Отыскать все заголовки, отобразить их в значения их атрибутов id,
// преобразовать результат в настоящий массив и отсортировать его.
$(":header").map(function() { return this.id; }).toArray().sort();

$() в сравнении с querySelectorAII()

Функция $() похожа на метод querySelectorAll() объектаDocument, с которым мы познакомились в разделе 15.2.5: оба принимают CSS-селектор в виде аргумента и возвращают объект, подобный массиву, хранящий элементы, соответствующие селектору. Библиотека jQuery использует метод querySelectorAll() в браузерах, поддерживающих его, однако существуют веские причины, почему в своих программах следует использовать функцию $(), а не метод querySelectorAll():

Наряду с методами each() и map() объект jQuery имеет еще один фундаментальный метод – index(). Этот метод принимает элемент в виде аргумента и возвращает его индекс в объекте jQuery или –1, если указанный элемент не будет найден. Однако, что типично для jQuery, метод index() имеет перегруженные версии. Если в качестве аргумента передать методу index() объект jQuery, он попытается отыскать первый элемент из этого объекта. Если передать строку, метод index() будет использовать ее как CSS-селектор и вернет индекс первого элемента в объекте jQuery, соответствующего селектору. А если вызвать метод index() без аргументов, он вернет индекс первого элемента в объекте jQuery среди элементов одного с ним уровня вложенности. Последним методом общего назначения объекта jQuery, с которым мы познакомимся здесь, является метод is(). Он принимает селектор в виде аргумента и возвращает true, если хотя бы один из выбранных элементов соответствует указанному селектору. Его можно использовать в функции обратного вызова, передаваемой методу each(), например:

$("div'").each(function() { // Для каждого элемента <div>
    if ($(this).is(":hidden")) return; // Пропустить скрытые элементы
// Выполнить операции с видимыми элементами
});

содержание 19.2. Методы чтения и записи объекта jQuery содержание

Простейшими и часто используемыми операциями, которые выполняются над объектами jQuery, являются операции чтения и изменения значений HTML-атрибутов, стилей CSS, содержимого элементов и их геометрии. В данном разделе описываются методы, используемые для выполнения этих операций. Однако перед этим необходимо сделать некоторые обобщения, касающиеся методов чтения и записи объекта jQuery:

Продолжая чтение раздела, помните об этих общих чертах методов чтения и записи. Каждый из следующих подразделов описывает отдельную категорию методов чтения/записи объекта jQuery.

содержание 19.2.1. Чтение и запись значений HTML-атрибутов

Метод attr() объекта jQuery – это метод чтения/записи значений HTML-атрибутов, и к нему относятся все обобщения, описанные выше. Метод attr() предусматривает решение проблемы несовместимости браузеров и обработку специальных случаев и позволяет использовать имена HTML-атрибутов или имена эквивалентных им свойств в языке JavaScript (где они отличаются). Например, можно использовать имя "for" или "htmlFor", "class" или "className". Связанная функция removeAttr() полностью удаляет атрибут из всех выбранных элементов. Ниже приводятся несколько примеров использования этих методов:

$("form").attr("action"); // Получить атрибут action 1-й формы
$("#icon" ).attr("src", "icon.gif"); // Установить атрибут src
$("#banner").attr({src:"banner.gif", alt:"Advertisement",
                                  width:720, height:64})
// Установить сразу 4 атрибута ;
$("a").attr("target", "_blank"); // Все ссылки загружать в новых окнах
$("a").attr("target", function() { // Локальные ссылки загружать локально
         if (this.host == location.host) return "_self"
         else return "_blank";
});

// Внешние ссылки загружать в новых окнах
$("a").attr({target: function() {...}}); // Можно также передать функцию
$("а").removeAttr("target"); // Все ссылки загружать в этом окне

содержание 19.2.2. Чтение и запись значений CSS-атрибутов

Метод css() напоминает метод attr(), но работает не с HTML-атрибутами, а со стилями CSS элемента. При чтении значений стилей метод css() возвращает текущий (или «вычисленный»; раздел 16.4) стиль элемента: возвращаемое значение может быть определено в атрибуте style или в таблице стилей. Обратите внимание, что нельзя получить значения составных стилей, таких как "font" или "margin". Вместо этого следует запрашивать отдельные стили, такие как "font-weight", "font-family", "margin-top" или "margin-left". При записи значений стилей метод css() просто добавляет их в атрибут style элемента. Метод css() позволяет указывать имена стилей CSS с дефисами ("background-color") или имена свойств в языке JavaScript с переменным регистром символов ("backgroundColor"). При чтении значений стилей метод css() возвращает числовые значения в виде строк с добавлением единиц измерения в конце. Однако при записи он преобразует числа в строки и добавляет суффикс "px" (pixels – пикселы), если это необходимо:

$("h1").css("font-weight"); // Насыщенность шрифта первого элемента <h1>
$("h1").css("fontWeight"); // Допускается использовать имена свойств
$("h1").css("font"); // Ошибка: нельзя запрашивать составные стили
$("h1").css("font-variant", "smallcaps"); // Установить стиль всех элементов <h1>
$("div.note").css("border", "solid black 2px"); // Составные стили можно устанавливать
$("h1").css({ backgroundColor: "black",
                       textColor: "white",
                       fontVariant: "small-caps"
                       padding: "10рх 2рх 4рх 20рх",
                       border: "dotted black 4px" })
// Записать сразу несколько стилей
// имена с переменным регистром
// лучше подходят на роль имен
// свойств объекта
// Увеличить размер шрифта во всех элементах <h1> на 25%
$("h1").css("font-size", function(i.curval) {
                                  return Math.round(1.25*parseInt(curval));
});

содержание 19.2.3. Чтение и запись CSS-классов

Напомню, что значение атрибута class (в языке JavaScript доступного в виде свойства className) интерпретируется как список имен классов CSS, разделенных пробелами. Обычно бывает необходимо добавить, удалить или проверить присутствие какого-то одного имени в списке, тогда как потребность замещать один список классов другим возникает крайне редко. По этой причине в объекте jQuery определены удобные методы для работы с атрибутом class. Методы addClass() и removeClass() добавляют и удаляют классы в выбранных элементах. Метод toggleClass() добавляет классы в элемент, если они отсутствуют в нем, и удаляет их, если они присутствуют. Метод hasClass() проверяет присутствие указанного класса. Ниже приводятся несколько примеров использования этих методов:

// Добавление CSS-классов
$("h1").addClass("hilite"); // Добавить класс во все элементы <h1>
$("h1+р").addClass("hilite first"); // Добавить 2 класса в <p> после <h1>
$("section").addClass(function(n) {
             return "section" + n;
});
// Передать функцию, чтобы добавить
// вычисляемый класс во все
// выбранные элементы
// Удаление CSS-классов
$("р").removeClass("hilite"); // Удалить класс из всех элементов <p>
$("р").removeClass("hilite first"); // Допустимо удалять несколько классов
$("section").removeClass(function(n) {
             return "section" + n;
});
// Удалить вычисляемый класс из элем.
$("div").removeClass(); // Удалить все классы из всех <div>
// Переключение CSS-классов
$("tг:odd").toggleClass("oddrow"); // Добавить класс, если отсутствует,
// или удалить в противном случае
$("h1").toggleClass("big bold"); // Переключить сразу два класса
$("h1').toggleClass(function(n) {
             return "big bold h1-" + n;
});
// Переключить вычисляемый класс
// или классы
$("h1").toggleClass("hilite", true); // Действует как addClass
$("h1").toggleClass("hilite", false); // Действует как removeClass
// Проверка CSS-классов
$("p").hasClass("first") // Имеет ли какой-нибудь <p> этот класс?
$("#lead").is(".first") // То же самое
$("#lead").is(".first.hilite") // is() – более гибкий, чем hasClass()
Обратите внимание, что метод hasClass() не такой гибкий, как методы addClass(), removeClass() и oggleClass()t. Метод hasClass() может работать только с одним именем класса и не поддерживает возможность передачи ему функции. Он возвращает true, если хотя бы один из выбранных элементов содержит указанный класс, и false – в противном случае. Метод is() (описываемый в разделе 19.1.2) более гибкий и может использоваться для той же цели.

Эти методы объекта jQuery подобны методам свойства classList, о котором рассказывалось в разделе 16.5, но методы объекта jQuery работают во всех браузерах, а не только в тех, которые поддерживают свойство classList, определяемое стандартом HTML5. И, конечно же, методы объекта jQuery работают с множеством элементов и могут добавляться в цепочки вызовов методов.

содержание 19.2.4. Чтение и запись значений элементов HTML-форм

Метод val() служит для чтения и записи значений атрибутов value элементов HTML-форм, а также для чтения и записи состояния выбора флажков, радиокнопок и элементов <select>:

$("#surname").val() // Получить значение текстового поля surname
$('"#usstate").val() // Получить единственное значение из элемента <select>
$("select#extras").val() // Получить массив значений из <select multiple>
$(''input: radio[name=ship]:checked").val() // Получить значение атрибута
// checked радиокнопки
$("#email").val("Invalid email address") // Установить значение текст, поля
$("input:checkbox").val(["opt1", "opt2"]) // Установить флажки с указанными именами
// или значениями
$("input:text").val(function() {
             return this.defaultValue;
});
// Сбросить все текстовые поля
// в значения по умолчанию

содержание 19.2.5. Чтение и запись содержимого элемента

Методы text() и html() читают и записывают содержимое элемента или элементов в виде простого текста или разметки HTML. При вызове без аргументов метод text() возвращает содержимое всех вложенных текстовых узлов из всех выбранных элементов в виде простого текста. Этот метод работает даже в браузерах, не поддерживающих свойства textContent и innerText (раздел 15.5.2). Если вызвать метод html() без аргументов, он вернет в виде разметки HTML содержимое только первого выбранного элемента. Для этой цели библиотека jQuery использует свойство innerHTML: x.html() – фактически то же самое, что и x[0].innerHTML. Если методам text() или html() передать строку, она будет использована как содержимое элемента в виде простого текста или разметки HTML и заместит текущее его содержимое. Подобно другим методам записи, с которыми мы уже познакомились, этим методам можно также передать функцию, которая будет использована для получения строки с новым содержимым:

var title = $("head title").text() // Получить заголовок документа
var headline = $("h1").html() // Получить разметку html первого <h1>
$("h1").text(function(n,current) {
             return "§" + (n+1) + ": " + current
});
// Добавить в каждый заголовок
// порядковый номер раздела

содержание 19.2.6. Чтение и запись параметров геометрии элемента

В разделе 15.8 мы узнали, насколько сложно бывает определить размер и координаты элемента, особенно в браузерах, не поддерживающих метод getBoundingClientRect() (раздел 15.8.2). Библиотека jQuery упрощает эти вычисления, предоставляя методы, работающие в любых браузерах. Обратите внимание, что все методы, описываемые здесь, являются методами чтения, и лишь некоторые из них могут использоваться для записи.

Метод offset() позволяет получить или изменить координаты элемента. Этот метод определяет координаты относительно начала документа и возвращает их в виде объекта со свойствами left и top, в которых хранятся координаты X и Y. Если передать методу объект с этими свойствами, он изменит координаты элемента в соответствии с указанными значениями. При необходимости он также установит CSS-атрибут position, чтобы сделать элемент позиционируемым:

var elt = $("#sprite"); // Элемент, который требуется переместить
var position = elt.offset(); // Получить текущие координаты
position.top += 100; // Изменить координату Y
elt.offset(position); // Переместить элемент в новую позицию
// Переместить все элементы <h1> вправо на расстояние, зависящее от их
// положения в документе
$("h1").offset(function(index,curpos) {
             return {left: curpos.left + 25*index, top:curpos.top};
});
Метод position() похож на метод offset(), за исключением того, что он позволяет только читать координаты и возвращает координаты элемента не относительно начала документа, а относительно его родителя. В разделе 15.8.5 мы узнали, что каждый элемент имеет свойство offsetParent, ссылающееся на родительский элемент, относительно которого определяются координаты. Позиционируемые элементы всегда играют роль начала координат для своих потомков, но некоторые браузеры дают эту роль и некоторым другим элементам, таким как ячейки таблицы. Роль начала координат в библиотеке jQuery могут играть только позиционируемые элементы, и метод offsetParent() объекта jQuery отображает каждый элемент на ближайший позиционируемый вмещающий элемент или на элемент <body>. Следует отметить не совсем удачный выбор имен этих методов: offset() возвращает абсолютные координаты элемента относительно начала документа, а метод position() возвращает смещение элемента относительно его ближайшего предка offsetParent().

Существует также три метода чтения, позволяющие получить ширину, и три метода чтения, – высоту элемента. Методы width() и height() возвращают базовые значения ширины и высоты, не включающие отступы, рамки и поля. Методы innerWidth() и innerHeight() возвращают ширину и высоту элемента с отступами (слово "inner" – внутренний – указывает на тот факт, что эти методы возвращают ширину и высоту внутри рамки). Методы outerWidth() и outerHeight() по умолчанию возвращают размеры элемента с отступами и рамкой. Если этим методам передать значение true, они добавят размеры полей элемента. Следующий фрагмент демонстрирует, что для элемента можно получить четыре разные ширины:

var body = $("body");
var contentWidth = body.width();
var paddingWidth = body.innerWidth();
var borderWidth = body.outerWidth();
var marginWidth = body.outerWidth(true);
var padding = paddingWidth-contentWidth; // сумма левого и правого отступов
var borders = borderWidth-paddingWidth; // сумма толщины левой и правой рамки
var margins = marginWidth-borderWidth; // сумма левого и правого полей
Методы width() и height() обладают свойствами, отсутствующими у других четырех методов (методов inner и outer). Во-первых, если первый элемент в объекте jQuery является объектом Window или Document, эти методы вернут размер видимой области окна или полный размер документа. Другие методы работают только с элементами, не являющимися окнами или документами.

Другая особенность методов width() и height() заключается в том, что они являются также методами записи. Если передать значение этим методам, они установят ширину или высоту всех элементов в объекте jQuery. (Обратите, однако, внимание, что они не могут изменять ширину или высоту объектов Window и Document.) Если аргумент имеет числовое значение, он будет интерпретироваться как число пикселов. Если передать строку, она будет использоваться как значение CSS-атрибута width или height, благодаря чему в ней можно указывать любые единицы измерения, предусматриваемые стандартом CSS. Наконец, как и другие методы записи, они могут принимать функцию, которая будет вызываться для вычисления значения ширины или высоты.

Между ролями чтения и записи методов width() и height() существует маленькое несоответствие. При использовании в качестве методов чтения они возвращают размеры элемента по содержимому, исключая отступы, рамки и поля. Однако при использовании в качестве методов записи они просто устанавливают CSS-атрибуты width и height. По умолчанию эти атрибуты также определяют размеры по содержимому. Но если элемент имеет CSS-атрибут box-sizing (раздел 16.2.3.1), установленный в значение border-box, методы width и height будут устанавливать размеры, включающие ширину отступов и рамок. Для элемента e, использующего блочную модель "content-box", вызов $(e).width(x).width() вернет значение x. Однако для элемента, использующего блочную модель "border-box", этот же вызов в общем случае вернет другое значение.

Последняя пара методов объекта jQuery, имеющих отношение к геометрии элементов, – это методы scrollTop() и scrollLeft(), позволяющие получить позиции полос прокрутки для элемента или множество позиций полос прокрутки для всех элементов. Эти методы могут применяться и к элементам документа, и к объекту Window, а при вызове для объекта Document они возвращают или устанавливают позиции полос прокрутки объекта Window, хранящего документ. В отличие от других методов записи, методам scrollTop() и scrollLeft() нельзя передавать функции. Метод scrollTop() как метод чтения и записи можно использовать в паре с методом height(), чтобы на их основе определить метод, прокручивающий окно на указанное число страниц:

// Прокручивает окно на n страниц, n может быть дробным и отрицательным числом
function page(n)
        var w = $(window);
        var pagesize = w.height();
        var current = w.scrollTop();
        w.scrollTop(current + n*pagesize);
}
// Обернуть окно объектом jQuery
// Получить размер страницы
// Текущие позиции полос прокрутки
// Установить новые позиции
// полос прокрутки

содержание 19.2.7. Чтение и запись данных в элементе

Библиотека jQuery определяет метод чтения/записи с именем data(), который возвращает или устанавливает данные, связанные с любым элементом документа или с объектами Document и Window. Возможность связывать данные с любыми элементами является одной из наиболее важных и мощных особенностей: она лежит в основе механизма регистрации обработчиков событий и последовательностей визуальных эффектов в библиотеке jQuery, и в определенных случаях метод data() может оказаться полезным в ваших сценариях.

Чтобы связать данные с элементами в объекте jQuery, нужно вызвать data() как метод записи, передав ему в виде двух аргументов имя и значение. Методу data() как методу записи можно также передать единственный объект, каждое свойство которого будет использоваться как пара имя/значение, связываемая с элементом или элементами в объекте jQuery. Однако обратите внимание, что, когда методу data() передается объект, свойства этого объекта будут замещать все данные, ранее связанные с элементом или элементами. В отличие от многих других методов записи, с которыми мы уже познакомились, метод data() не вызывает функцию, переданную ему. Если во втором аргументе передать методу data() функцию, она будет сохранена, как любое другое значение.

Конечно, метод data() может также использоваться в роли метода чтения. При вызове без аргументов он возвращает объект, содержащий все пары имя/значение, связанные с первым элементом в объекте jQuery. При вызове метода data() с единственным строковым аргументом он возвращает значение, связанное с этой строкой в первом элементе.

Для удаления данных из элемента или элементов можно использовать метод removeData() (вызов метода data() с именованным значением null или undefined фактически не удаляет данные). Если методу removeData() передать строку, он удалит значение, связанное с этой строкой в элементе или элементах. Если вызвать метод removeData() без аргументов, он удалит все данные:

$("div").data("x", 1); // Записать некоторые данные/ Set some data
$("div.nodata").removeData("x"); // Удалить некоторые данные/ Remove some data
var x = $('#mydiv').data("x") // Получить некоторые данные/ Query some data
Кроме того, библиотека jQuery определяет вспомогательные функции, действующие аналогично методам data() и removeData() . Таким образом, связать данные с отдельным элементом e можно с помощью метода или функции data():
$(e).data(...) // метод/ The method form
$.data(e, ...) // функция/ The function form
Механизм хранения данных в библиотеке jQuery не использует для этой цели свойства самих элементов, но добавляет одно специальное свойство ко всем элементам, имеющим связанные с ними данные. Некоторые браузеры не позволяют добавлять свойства к элементам <applet>, <object> и <embed>, поэтому библиотека jQuery просто не дает возможности связать данные с элементами этих типов.

содержание 19.3. Изменение структуры документа содержание

В разделе 19.2.5 мы познакомились с методами html() и text(), позволяющими изменять содержимое элемента. В этом разделе будут рассматриваться методы, позволяющие производить более сложные изменения в документе. В браузере HTML-документы представлены в виде дерева узлов, а не в виде линейной последовательности символов, поэтому вставку, удаление и замену фрагмента документа выполнить не так просто, как фрагмента строки или массива. В следующих подразделах описываются различные методы объекта code>jQuery, предназначенные для внесения изменений в документ.

содержание 19.3.1. Вставка и замена элементов

Начнем с самых основных методов вставки и замены. Все методы, демонстрирующиеся ниже, принимают аргумент, определяющий содержимое, которое должно быть вставлено в документ. Это может быть строка с простым текстом или с разметкой HTML, определяющая содержимое, объект jQuery, элемент Element или текстовый узел Node. Вставка может быть выполнена внутрь, перед, после или вместо (в зависимости от метода) каждого выбранного элемента. Если в качестве вставляемого содержимого используется элемент, уже присутствующий в документе, он перемещается из текущего местоположения. Если выполняется вставка сразу в несколько мест, элемент будет скопирован необходимое число раз. Все эти методы возвращают объект jQuery, относительно которого они вызываются. Обратите, однако, внимание, что после вызова метода replaceWith() элементы, находящиеся в объекте jQuery, исключаются из документа:

$("#log").append("<br/>"+message); // Добавить содержимое в конец элемента #log
$("h1").prepend("§"); // Добавить символ параграфа в начало каждого элемента <h1>
$("h1").before("<hr/>"); // Вставить линию перед каждым элементом <h1>
$("h1").after("<hr/>"); // и после
$("hr").replaceWith("<br/>"); // Заменить элементы <hr/> на <br/>
$("h2").each(function() {
               var h2 = $(this);
// Заменить <h2> на <h1>,
// сохранив содержимое.
               h2.replaceWith("<h1>" + h2.html() + "</h1>");
        });
// Методы after() и before() могут также применяться к текстовым узлам
// Ниже демонстрируется другой способ добавления символа параграфа во все <h1>
$("h1").map(function() { return this.firstChild; }).before("§");
Каждый из этих пяти методов, изменяющих структуру документа, может также принимать функцию, которая должна вызываться для вычисления вставляемого значения. Как обычно, в этом случае функция будет вызываться по одному разу для каждого выбранного элемента. Ссылка this в ней будет указывать на текущий элемент, а в первом аргументе ей будет передаваться индекс элемента в объекте jQuery. Методы append()E, prepend()E и replaceWith() будут передавать функции во втором аргументе текущее содержимое элемента в виде строки с разметкой HTML. А методы before() и after() будут вызывать функцию без второго аргумента. Все пять методов, представленные выше, применяются к целевым элементам и принимают вставляемое содержимое в виде аргумента. Для каждого из этих пяти методов имеется парный метод, действующий в обратном порядке: он вызывается относительно содержимого и принимает целевые элементы в виде аргументов. Пары методов перечислены в следующей таблице:
Операция $(элементы).метод(содержимое) $(содержимое).метод(элементы)
вставка содержимого в конец целевого элемента append() appendTo()
вставка содержимого в начало целевого элемента prepend() prependTo()
вставка содержимого после целевого элемента after() insertAfter()
вставка содержимого перед целевым элементом before() insertbefore()
замена целевого элемента содержимым replaceWith() replaceAll()
Методы, продемонстрированные в приведенном выше примере, перечислены во втором столбце. Методы, перечисленные в третьем столбце, будут демонстрироваться ниже. Есть несколько важных замечаний, касающихся этих пар методов:

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

$("<br/>+message").appendTo("#log"); // Добавить разметку html в #log
$(document.createTextNode("§")).prependTo( "h1"); // Добавить текстовый узел во все <h1>
$("<hr/>"). insertBefore("h1"); // Вставить линию перед каждым <h1>
$("<hr/>"). insertAfter("h1"); // Вставить линию после каждого <h1>
$("<br/>").replaceAll("hr"); // Заменить элементы <hr/> на <br/>

содержание 19.3.2. Копирование элементов

Как отмечалось выше, при вставке элементов, уже являющихся частью документа, эти элементы не копируются, а просто перемещаются в новое местоположение. Если элемент вставляется в несколько мест, библиотека jQuery скопирует элемент столько раз, сколько потребуется, но копирование не выполняется при вставке только в одно местоположение. Если потребуется не переместить, а скопировать элемент, необходимо сначала создать копию с помощью метода clone(). Метод clone() создает и возвращает копии всех выбранных элементов (и всех потомков этих элементов). Копии элементов, находящиеся в возвращаемом объекте jQuery, не являются частью документа, но их можно вставить в документ с помощью любого из методов, представленных выше:

// Добавить новый div с атрибутом id="linklist" в конец документа
$(document.body).append("<div id='linklist'><h1>List of Links</h1></div>");
// Скопировать все ссылки в документе и вставить их в этот новый div
$("a").clone().appendTo("#linklist");
// Вставить элементы <br/> после каждой ссылки, чтобы они отображались в отдельных строках
$("#linklist > a").after("<br/>");
По умолчанию метод clone() не копирует обработчики событий (раздел 19.4) и другие данные (раздел 19.2.7), связанные с элементами. Если необходимо будет скопировать эти дополнительные данные, передайте методу clone() значение true.

содержание 19.3.3. Обертывание элементов

Другой способ вставки элементов в HTML-документ связан с обертыванием новым элементом (или элементами) одного или более элементов. Объект jQuery определяет три метода обертывания. Метод wrap() обертывает каждый выбранный элемент. Метод wraplnner() обертывает содержимое каждого выбранного элемента. А метод wrapAll() обертывает все выбранные элементы как единое целое. По умолчанию этим методам передается вновь созданный обертывающий элемент или строка с разметкой HTML, которая будет использована для создания обертки. Строка с разметкой HTML может включать вложенные элементы, если это необходимо, но на самом верхнем уровне она должна содержать единственный элемент. Если любому из этих методов передать функцию, она будет вызываться по одному разу в контексте каждого элемента (с индексом элемента в виде единственного аргумента) и должна возвращать строку, элемент Element или объект jQuery. Например:

// Обернуть каждый элемент <h1> элементом <i>
$("h1").wrap(document.createElement("i")); // Результат: <i><h1>.. .</h1><i>
// Обернуть содержимое каждого элемента <h1>. Строковый аргумент проще в использовании.
$("h1").wrapInner("<i/>");                 // Результат: <h1><i>.. .</h1><i>
// Обернуть первый абзац якорем и элементом div
$("body>p:first").wrap("<a name='lead'><div class='first'></div></a>");
// Обернуть все остальные абзацы другим элементом div
$("body>p:not(:first)").wrapAll("<div class='rest'></div>");

содержание 19.3.4. Удаление элементов

Помимо методов вставки и замены в объекте jQuery имеются также методы удаления элементов. Метод empty() удаляет все дочерние элементы (включая текстовые узлы) из каждого выбранного элемента без изменения самого элемента. Метод remove(), напротив, удаляет из документа все выбранные элементы (и все их содержимое). Обычно метод remove() вызывается без аргументов и удаляет все элементы, находящиеся в объекте jQuery. Однако если передать методу аргумент, этот аргумент будет интерпретироваться как селектор, и удалены будут только элементы из объекта jQuery, соответствующие селектору (Если необходимо удалить элементы из множества выбранных элементов, не удаляя их из документа, используйте метод filter(), о котором рассказывается в разделе 19.8.2)). Обратите внимание, что не требуется удалять элементы перед повторной их вставкой в документ: достаточно просто вставить их в новое местоположение, а библиотека автоматически переместит их.

Метод remove() удаляет также все обработчики событий (раздел 19.4) и другие данные (раздел 19.2.7), которые могли быть связаны с удаляемыми элементами. Метод detach() действует подобно методу remove(), но не удаляет обработчики событий и данные. Метод detach() может оказаться удобнее, когда элементы требуется удалить из документа на время и позднее вставить их обратно. Наконец, метод unwrap() выполняет удаление элементов способом, противоположным тому, каким действует метод wrap() или wrapAll(): он удаляет родительский элемент каждого выбранного элемента, не оказывая влияния на выбранные элементы и их братские элементы. То есть для каждого выбранного элемента он замещает родителя этого элемента его дочерними элементами. В отличие от методов remove() и detach(), метод unwrap() не принимает необязательный аргумент с селектором.

содержание 19.4. Обработка событий с помощью библиотеки jQuery содержание

Как мы узнали в главе 17, одна из сложностей, связанных с обработкой событий, состоит в том, что в IE (до версии IE9) реализована модель событий, отличающаяся от модели событий в других браузерах. Чтобы решить эту проблему, в библиотеке jQuery определяется собственная унифицированная модель событий, которая одинаково работает во всех браузерах. В простейших случаях модель jQuery API оказывается проще в использовании, чем стандартная модель или модель IE. В более сложных случаях модель jQuery предоставляет более широкие возможности, чем стандартная модель. Все дополнительные подробности описываются в следующих подразделах.

содержание 19.4.1. Простые методы регистрации обработчиков событий

Библиотека jQuery определяет простые методы регистрации обработчиков для всех наиболее часто используемых событий, поддерживаемых всеми браузерами. Например, чтобы зарегистрировать обработчик события "click", достаточно просто вызвать метод click():

// Щелчок на любом элементе <p> окрашивает его фон в серый цвет
$('p').click(function() { $(this).css("background-color", "gray"); });
Вызов метода объекта jQuery регистрации обработчика событий зарегистрирует указанный обработчик во всех выбранных элементах. Обычно это проще, чем регистрировать один и тот же обработчик во всех элементах по отдельности с помощью метода addEventListener() или attachEvent().

Библиотека jQuery определяет следующие простые методы регистрации обработчиков событий:

blur() focusin() mousedown() mouseup()
change() focusout() mouseenter() resize()
click() keydown() mouseleave() scroll()
dblclick() keypress() mousemove() select()
error() keyup() mouseout() submit()
focus() load() mouseover() unload()

Большая часть этих методов регистрации обработчиков наиболее часто используемых типов событий уже знакомы вам по главе 17. Тем не менее необходимо сделать несколько замечаний. События "focus" и "blur" не всплывают, в отличие от всплывающих событий "focusin" и "focusout", и библиотека jQuery гарантирует, что эти события будут работать во всех браузерах. События "mouseover" и "mouseout", наоборот, всплывают, и это часто доставляет неудобства, так как сложно определить – указатель мыши покинул интересующий нас элемент или событие было доставлено от одного из потомков. События "mouseenter" и "mouseleave" не всплывают, что решает данную проблему. Эти типы событий впервые появились в IE, но библиотека jQuery гарантирует, что они корректно будут работать во всех браузерах. События "resize" и "unload" возбуждаются только в объекте Window, поэтому, если потребуется зарегистрировать обработчики этих типов событий, методы resize() и unload() следует вызывать относительно $(window). Метод scroll() часто вызывается относительно $(window), но его также можно вызывать относительно любых элементов, имеющих полосы прокрутки (например, относительно элементов, в которых CSS-атрибут overflow имеет значение "scroll" или "auto"). Метод load() может вызываться относительно $(window), для регистрации обработчика события "load" окна, но обычно проще бывает передать свою функцию инициализации непосредственно функции $(), как показано в разделе 19.1.1. При этом метод load() с успехом можно использовать в элементах <iframe> и <img>. Обратите внимание, что при вызове метода load() с различными аргументами он также может использоваться для загрузки нового содержимого (по протоколу HTTP) в элемент (раздел 19.6.1). Метод error() можно использовать с элементами <img> для регистрации обработчиков неудачи загрузки изображения. Он не должен использоваться для установки свойства onerror объекта Window, описанного в разделе 14.6.

В дополнение к этим простым методам регистрации обработчиков событий существуют две специальные формы методов, которые могут иногда пригодиться. Метод hover() регистрирует обработчики событий "mouseenter" и "mouseleave". Вызов hover(f,g) по своему действию аналогичен двум последовательным вызовам методов mouseenter(f) и mouseleave(g). Если методу hover() передать единственный аргумент, он будет использоваться как обработчик обоих событий.

Другим специальным методом регистрации обработчиков событий является метод toggle(). Этот метод регистрирует функцию обработчика события "click". Вы можете указать две или более функции обработчиков, и библиотека jQuery будет вызывать их всякий раз, когда будет возникать событие "click". Если, например, вызвать этот метод как toggle(f,g,h), функция f() будет вызываться для обработки первого события "click", g() – второго, h() – третьего и снова f() – для обработки четвертого события "click". Будьте внимательны при использовании метода toggle(): как будет показано в разделе 19.5.1 , этот метод может также использоваться для отображения и скрытия (т. е. для переключения видимости) выбранных элементов.

В разделе 19.4.4 мы познакомимся с другими, более обобщенными способами регистрации обработчиков событий, и завершим этот раздел описанием еще одного простого и удобного способа регистрации обработчиков.

Напомню, что создавать новые элементы можно с помощью функции $(), передавая ей строку с разметкой HTML и объект (во втором аргументе) с атрибутами, которые должны быть установлены во вновь созданном элементе. Второй аргумент может быть любым объектом, который допускается передавать методу attr(). Но кроме того, если имя какого-либо из свойств совпадает с именем метода регистрации обработчиков событий, перечисленных выше, значение этого свойства будет интерпретироваться как функция-обработчик и зарегистрировано как обработчик данного типа события. Например:

$("<img/>", {
    src: image_url,
    alt: image_description,
    className: "translucent_image",
    click: function() { $(this).css("opacity", "50%"); }
});

содержание 19.4.2. Обработчики событий в библиотеке jQuery

Функции обработчиков событий в примерах, приведенных выше, не имеют ни аргументов, ни возвращаемых значений. В целом это нормально для подобных обработчиков событий, но библиотека jQuery передает каждому обработчику событий один или более аргументов и анализирует значения, возвращаемые ими. Самое главное, что следует знать, – каждому обработчику событий библиотека jQuery передает в первом аргументе объект события. Поля этого объекта содержат дополнительную информацию о событии (такую как координаты указателя мыши). Свойства стандартного объекта Event были описаны в главе 17. Библиотека jQuery имитирует стандартный объект Event даже в браузерах (таких как IE версии 8 и ниже), не поддерживающих его, и объекты событий в библиотеке jQuery имеют одинаковые наборы полей во всех браузерах. Подробнее об этом рассказывается в разделе 19.4.3. Обычно обработчикам событий передается единственный аргумент с объектом события. Но если событие генерируется явно с помощью метода trigger()(раздел 19.4.6), обработчикам можно передавать массив дополнительных аргументов. В этом случае дополнительные аргументы передаются обработчикам после первого аргумента с объектом события.

Независимо от способа регистрации значение, возвращаемое функцией обработчика событий, всегда имеет большое значение для библиотеки jQuery. Если обработчик вернет false, будут отменены и действия, предусмотренные по умолчанию для этого типа события, и дальнейшее распространение события. То есть возврат значения false равносилен вызову методов preventDefault() и stopPropagation() объекта Event. Кроме того, когда обработчик события возвращает значение (отличное от undefined), библиотека jQuery сохраняет это значение в свойстве result объекта Event, к которому можно обратиться в обработчиках событий, вызываемых вслед за этим обработчиком.

содержание 19.4.3. Объект Event в библиотеке jQuery

Библиотека jQuery скрывает различия в реализациях браузеров, определяя собственный объект Event. Когда библиотека jQuery вызывает обработчик события, она всегда передает ему в первом аргументе собственный объект Event. Объект Event в библиотеке jQuery основан на положениях стандартов консорциума W3C, но в нем также реализованы некоторые особенности, ставшие стандартными де-факто. jQuery копирует все следующие поля стандартного объекта Event во все свои объекты Event (хотя некоторые из них могут иметь значение undefined для определенных типов событий):

altKey ctrlKey newValue screenX
attrChange currentTarget offsetX screenY
attrName detail offsetY shiftKey
bubbles eventPhase originalTarget srcElement
button /td> fromElement pageX target
cancelable keyCode pageY toElement
charCode layerX prevValue view
clientX layerY relatedNode wheelDelta
clientY metaKey relatedTarget which

В дополнение к этим свойствам объект Event определяет также следующие методы:

preventDefault() isDefaultPrevented()
stopPropagation() isPropagationStopped()
stopImmediatePropagation() isImmediatePropagationStopped()

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

metaKey

Если стандартный объект события не имеет свойства metaKey, jQuery присваивает ему значение свойства ctrlKey. Значение свойства metaKey определяется в MacOS клавишей Command.

pageX, pageY

Если стандартный объект события не имеет этих свойств, но имеет свойства, определяющие координаты указателя мыши в видимой области в виде свойств clientX и clientY, jQuery вычислит координаты указателя мыши относительно начала документа и сохранит их в свойствах pageX и pageY.

target, currentTarget, relatedTarget

Свойство target ссылается на элемент документа, в котором возникло событие. Если это свойство в стандартном объекте события ссылается на текстовый узел, jQuery подставит ссылку на вмещающий объект Element. Свойство currentTarget ссылается на элемент, в котором был зарегистрирован текущий обработчик события. Значение этого свойства всегда должно совпадать со значением this. Если значения свойств currentTarget и target не совпадают, следовательно, обрабатывается всплывшее событие и может оказаться полезным проверить элемент target с помощью метода is() (раздел 19.1.2):

if ($(event.target).is("a")) return; // Игнорировать события, сгенерированные в ссылках
Свойство relatedTarget – ссылка на другой элемент, вовлеченный в события перехода, такие как "mouseover" и "mouseout". Например, для событий "mouseover" свойство relatedTarget будет ссылаться на элемент, который покинул указатель мыши при перемещении на элемент target. Если стандартный объект события не имеет свойства relatedTarget, но имеет свойства toElement и fromElement, свойство relatedTarget получает значение одного из этих свойств в зависимости от типа события.

timeStamp

Время возникновения события в миллисекундах, возвращаемое методом Date.getTime(). Библиотека jQuery сама устанавливает это свойство, чтобы обойти давнишнюю ошибку в Firefox.

which

Библиотека jQuery нормализует это нестандартное свойство события так, что оно определяет кнопку мыши или клавишу на клавиатуре, нажатие которой вызвало это событие. Для событий клавиатуры, если стандартный объект события не имеет свойства which, но имеет свойство charCode или keyCode, в свойство which будет записано значение свойства, которое определено. Для событий мыши, если свойство which отсутствует, но имеется свойство button, в свойство which будет записано значение, основанное на значении свойства button. О означает, что никакая кнопка не была нажата. 1 – была нажата левая кнопка, 2 – средняя кнопка и 3 – правая кнопка. (Обратите внимание, что в некоторых браузерах нажатие правой кнопки мыши не генерирует события.)

Кроме того, библиотека jQuery определяет следующие собственные поля в объекте Event, которые иногда могут оказаться полезными:

data

Если при регистрации обработчика события были указаны дополнительные данные (раздел 19.4.4), обработчик сможет получить к ним доступ с помощью этого поля.

handler

Ссылка на текущую функцию обработчика события.

result

Возвращаемое значение предыдущего обработчика этого события. Обработчики, не возвращающие ничего, не учитываются.

originalEvent

Ссылка на стандартный объект Event, созданный браузером.

содержание 19.4.4. Дополнительные способы регистраци обработчиков событий

Мы уже знаем, что в библиотеке jQuery имеется множество простых методов регистрации обработчиков событий. Каждый из них просто вызывает единый более сложный метод bind(), что Внутри каждого из них вызывает один и тот же, более сложный метод bind(), который связывает обработчик с указанным типом события во всех элементах в объекте jQuery. Прямое использование метода bind() позволяет использовать дополнительные возможности механизма регистрации, недоступные в простых методах.

В библиотеке jQuery термин «связывание» используется для обозначения регистрации обработчиков событий. Стандарт ECMAScript 5, и многие фреймворки на языке JavaScript определяют в объектах функций метод bind() (раздел 8.7.4) и используют этот термин для обозначения связи функций с объектами, относительно которых они вызываются. Версия метода Function.bind() в библиотеке jQuery является вспомогательной функцией с именем jQuery.proxy(), которая описывается в разделе 19.7 .

В простейшем случае методу bind()) передаются строка с типом события в первом аргументе и функция обработчика события во втором. Простые методы регистрации обработчиков событий используют именно эту форму вызова метода bind(). Вызов $('p').click(f);, например, эквивалентен вызову:

$('p').bind('click', f);
Метод bind() может также вызываться с тремя аргументами. В этой форме вызова тип события передается в первом аргументе, а функция обработчика – в третьем. Во втором аргументе можно передать любое значение, и библиотека jQuery будет присваивать это значение свойству data объекта Event перед вызовом обработчика. Иногда это может пригодиться для передачи обработчику дополнительных данных без использования замыкания.

Кроме того, bind() обладает еще одной дополнительной особенностью. Если в первом аргументе передать список типов событий, разделенных пробелами, то функция обработчика будет зарегистрирована для всех указанных типов событий. Вызов $('a').hover(f) $('a').hover(f) (раздел 19.4.1 ), например, эквивалентен вызову:

$('a').bind('mouseenter mouseleave', f);
Еще одной важной особенностью метода bind() является возможность указать при регистрации пространство (или пространства) имен для обработчиков событий. Это дает возможность определить группу обработчиков событий, что может пригодиться, когда позднее потребуется переключать или удалять обработчики из определенного пространства имен. Поддержка пространств имен для обработчиков особенно удобна для тех, кто пишет библиотеки или модули, использующие библиотеку jQuery. Пространства имен событий подобны селекторам CSS-классов. Чтобы связать обработчик события с определенным пространством имен, добавьте точку и имя пространства имен после типа события:
// Связать f как обработчик события mouseover в пространстве имен "myMod" ко всем элементам <a>
$('a').bind('mouseover.myMod', f);
Имеется даже возможность связать обработчик с несколькими пространствами имен, например:
// Связать f, как обработчик события mouseout в пространствах имен "myMod" и "yourMod"
$('a').bind('mouseout.myMod.yourMod', f);;
Последней особенностью метода bind() является возможность передать ему в первом аргументе объект, отображающий имена событий в функции обработчиков. Возьмем еще раз в качестве примера метод hover(). Вызов $('a').hover(f,g) эквивалентен вызову:
$('a').bind({mouseenter:f, mouseleave:g});
При использовании этой формы метода bind() именами свойств передаваемого ему объекта могут быть строки со списками типов событий, разделенных запятыми, включающими пространства имен. Если в этом случае передать второй аргумент, его значение будет использоваться как дополнительные данные для всех связанных обработчиков.

Библиотека jQuery имеет еще один метод регистрации обработчиков. Метод one() вызывается и действует подобно методу bind()), за исключением того, что зарегистрированный с его помощью обработчик события автоматически удаляется после первого вызова. То есть, как следует из имени метода, обработчики событий, зарегистрированные с помощью one(), никогда не вызываются более одного раза. Единственное, чем не обладают методы bind()) и one(), – это возможность регистрации перехватывающих обработчиков событий, которая поддерживается методом addEventListener() (раздел 17.2.3). IE (до версии IE9) не поддерживает перехватывающие обработчики, и библиотека jQuery не пытается имитировать эту особенность.

содержание 19.4.5. Удаление обработчиков событий

После регистрации обработчика событий с помощью метода bind() (или с помощью простых методов регистрации обработчиков) его можно удалить с помощью метода unbind(), чтобы предотвратить его вызов при появлении событий в будущем (обратите внимание, что метод unbind() удаляет только обработчики, зарегистрированные методом bind() и родственными ему методами объекта jQueryy. Он не удаляет обработчики, зарегистрированные с помощью метода addEventListener() или attachEvent(), а также не удаляет обработчики, объявленные в атрибутах элементов, таких как onclick и onmouseover). При вызове без аргументов метод unbind() удалит все обработчики событий (для всех типов событий) из всех выбранных элементов в объекте jQuery:

$('*').unbind(); // Удалит все обработчики событий из всех элементов!
При вызове с единственным строковым аргументом он удалит все обработчики указанного типа события (или типов, если строка содержит несколько имен) из всех выбранных элементов в объекте jQuery:
// Удалить все обработчики событий mouseover и mouseout во всех элементах <a>
$('a').unbind("mouseover mouseout");
Это не самый лучший подход, и его не следует использовать при разработке модулей, потому что пользователь модуля может использовать другие модули, регистрирующие свои собственные обработчики этих же типов событий в тех же элементах. Однако если модуль будет регистрировать обработчики событий с использованием пространств имен, можно будет использовать эту версию вызова метода unbind() с одним аргументом для удаления только обработчиков события из вашего пространства или пространств имен:
// Удалить все обработчики событий mouseover и mouseout в пространстве имен "myMod"
$('a').unbind("mouseover.myMod mouseout.myMod");
// Удалить только обработчики событий из пространства имен myMod
$('a').unbind(".myMod");
// Удалить обработчик события click из пространств имен "ns1" и "ns2"
$('a').unbind("click.ns1.ns2");
Если потребуется удалить только те обработчики событий, которые были зарегистрированы вами, и вы не использовали пространства имен, вы должны получить ссылки на функции обработчиков событий и использовать версию вызова метода unbind() с двумя аргументами. В этом случае в первом аргументе передается строка с типом события (без указания пространств имен), а во втором – функция-обработчик:
$('#mybutton').unbind('click', myClickHandler);
При вызове метода unbind()) таким способом он удалит указанный обработчик указанного типа (или типов) события из всех выбранных элементов в объекте jQuery. Обратите внимание, что обработчики событий могут удаляться версией метода unbind() с двумя аргументами, даже когда они были зарегистрированы с дополнительными данными, с помощью версии метода bind(), принимающей три аргумента.

Методу unbind() можно также передавать объект в единственном аргументе. В этом случае метод unbind() будет вызываться рекурсивно для каждого свойства объекта. Имена свойств этого объекта должны определять типы событий, а значения – функции обработчиков:

$('a').unbind({ // $('a").unbind({ // Удалить конкретные обработчики событий mouseover и mouseout
mouseover: mouseoverHandler,
mouseout: mouseoutHandler
});
Наконец, существует еще один способ вызова метода unbind(). Если передать ему объект Event, созданный библиотекой jQuery, он удалит обработчики событий, которым будет передано это событие. Вызов unbind(ev) эквивалентен вызову unbind(ev.type, ev.handler).

содержание 19.4.6. Возбуждение событий

Зарегистрированные обработчики событий будут вызываться автоматически, когда пользователь начнет использовать мышь или клавиатуру или когда будут возникать события других типов. Однако иногда бывает полезно генерировать события вручную. Проще всего сделать это, вызвав один из простых методов регистрации обработчиков (такой как click() или mouseover()) без аргументов. Подобно многим методам объекта jQuery, которые могут играть роль методов чтения и записи, эти методы регистрируют обработчики событий, когда вызываются с аргументами, и запускают их, когда вызываются без аргументов. Например:

$("#my_form").submit(); // Будет действовать, как если бы пользователь щелкнул на кнопке отправки формы
Метод submit() в инструкции выше синтезирует объект Event и запустит все обработчики событий, которые были зарегистрированы для события "submit". Если ни один из этих обработчиков не вернет false или не вызовет метод preventDefault() объекта Event, форма действительно будет отправлена. Обратите внимание, что события будут всплывать, даже если сгенерировать их вручную, как в данном примере. Это означает, что возбуждение события в множестве выбранных элементов может также привести к вызову обработчиков событий в предках этих элементов. Важно отметить, что методы объекта jQuery, генерирующие события, будут запускать любые обработчики событий, зарегистрированные методами объекта jQuery, а также обработчики, объявленные в HTML-атрибутах или свойствах объектов Element, таких как onsubmit. Но с их помощью невозможно вручную запустить обработчики событий, зарегистрированные методом addEventListener() или attachEvent() (однако эти обработчики по-прежнему будут вызываться при возникновении настоящих событий).

Отметьте также, что механизм возбуждения событий в библиотеке jQuery является синхронным – в нем не используется очередь событий. Когда событие генерируется вручную, обработчики событий будут вызваны немедленно, до того как метод, возбудивший событие, вернет управление. Если вы генерируете событие ♦click" и один из запущенных обработчиков сгенерирует событие "submit", все обработчики события "submit" будут вызваны до того, как будет вызван следующий обработчик события "click".

Методы, такие как submit(), удобно использовать для связывания и возбуждения событий; но как библиотека jQuery определяет более обобщенный метод bind()), так же она определяет и более обобщенный метод trigger(). Обычно при вызове в первом аргументе методу trigger() передается строка с типом события, и он запускает обработчики, зарегистрированные для этого типа во всех выбранных элементах в объекте jQuery. To есть вызов submit() в примере выше эквивалентен вызову:

$("#my_form").trigger("submit");
В отличие от методов bind() и unbind(), в вызове метода trigger() нельзя указать более одного типа события в первом аргументе. Однако, подобно методам bind() и unbind(), он позволяет указывать пространства имен возбуждаемых событий» чтобы запустить только обработчики, зарегистрированные для этого пространства имен. Если потребуется запустить только обработчики событий, не привязанные ни к какому пространству имен, следует добавить в строку с типом события восклицательный знак. Обработчики, зарегистрированные посредством свойств, таких как onclick, считаются обработчиками, не привязанными к какому-либо пространству имен:
$("button").trigger("click.ns1"); // Запустит обработчики в пространстве имен
$("button").trigger("click!"); // Запустит обработчики, не привязанные к какому-либо пространству имен
Вместо строки с типом события в первом аргументе методу trigger() можно передать объект Event (или любой другой объект, имеющий свойство type). Свойство type будет определять, какие обработчики должны запускаться. Если передать объект Event библиотеки jQuery, этот объект будет передан обработчикам. Если передать простой объект, автоматически будет создан новый объект Event библиотеки jQuery и в него будут добавлены свойства объекта, переданного методу. Это самый простой способ передать обработчикам событий дополнительные данные:
// Обработчик onclick элемента buttonl генерирует то же событие для button2
$('#button1').click(function(e) { $('#button2').trigger(e); });

// Добавит дополнительные свойства в объект события при возбуждении события
$('#button1').trigger({type:'click', synthetic:true});

// Этот обработчик проверяет дополнительные свойства, чтобы отличить
// настоящее событие от искусственного
$('#button1').click(function(e) { if (e.synthetic) {...}; });
Передать дополнительные данные обработчикам при возбуждении событий вручную можно также с помощью второго аргумента метода trigger(). Значение, переданное методу trigger() во втором аргументе, будет передаваться во втором аргументе всем запущенным обработчикам событий. Если во втором аргументе передать массив, каждый его элемент будет передан обработчикам в виде отдельного аргумента:
$('#button1').trigger("click", true); // Передать единственный дополнительный аргумент
$('#button1').trigger("click", [x,y,z]); // Передать три дополнительных аргумента
Иногда может потребоваться запустить все обработчики события данного типа, независимо от того, к какому элементу документа они привязаны. Для этого можно выбрать все элементы вызовом $('*') и вызвать метод trigger() относительно результата, но это решение весьма неэффективно. Вместо того чтобы возбуждать событие в глобальном масштабе, можно вызвать вспомогательную функцию jQuery.event.trigger(). Эта функция принимает те же аргументы, что и метод trigger(), и эффективно запускает обработчики событий указанного типа, имеющиеся во всем документе. Обратите внимание, что «глобальные события», возбуждаемые таким способом, не всплывают, и при этом запускаются только обработчики событий, зарегистрированные с использованием методов объекта jQuery (обработчики, зарегистрированные с помощью свойств модели DOM, не запускаются).

После вызова обработчиков событий метод trigger() (и вспомогательные методы, вызывающие его) выполняет действия, предусмотренные по умолчанию для сгенерированного типа события (предполагается, что ни один обработчик не вернул значение false или не вызвал метод preventDefault() объекта события). Например, если возбудить событие "submit" в элементе <form>, метод trigger() вызовет метод submit() этой формы, а если возбудить в элементе событие "focus", метод trigger() вызовет метод focus() этого элемента.

Если необходимо вызвать обработчики событий без выполнения действий по умолчанию, вместо метода trigger() следует использовать метод triggerHandler(). Этот метод действует точно так же, как и метод trigger(), за исключением того, что он сначала вызывает методы preventDefault() и cancelBubble() объекта Event. Это означает, что искусственное событие не будет всплывать и для него не будут выполняться действия, предусмотренные по умолчанию.

содержание 19.4.7. Реализация собственных событий

Система управления событиями в библиотеке jQuery создана на основе стандартных событий, таких как щелчки мышью или нажатия клавиш, генерируемых веб-браузерами. Но она не ограничивается только этими событиями и позволяет использовать любую строку в качестве имени типа события. Метод bind() позволяет регистрировать обработчики таких «нестандартных событий», а метод trigger() – вызывать эти обработчики.

Такая разновидность косвенного вызова обработчиков нестандартных событий может оказаться весьма полезной при разработке модулей и реализации модели издатель/подписчик или шаблона Observer (наблюдатель). Зачастую при использовании собственных событий может оказаться полезной возможность возбуждать их глобально, с помощью функции jQuery.event.trigger() вместо метода trigger():

// Когда пользователь щелкнет на кнопке "logoff", отправить собственное событие
// всем подписанным на него наблюдателям, которые должны сохранить информацию
// о своем состоянии, и затем перейти на страницу выхода.
$("#logoff").click(function() {
  $.event.trigger("logoff"); // Отправить широковещательное событие
  window.location = "logoff.php"; // Перейти на другую страницу
});
В разделе 19.6.4 вы узнаете, что методы поддержки архитектуры Ajax в библиотеке jQuery аналогичным образом рассылают широковещательные события заинтересованным приемникам.

содержание 19.4.8. Динамические события

Метод bind() связывает обработчики событий с конкретными элементами документа, подобно методам addEventListener() и attachEvent() (глава 17). Но веб-приложения, использующие библиотеку jQuery, часто создают новые элементы динамически. Если мы воспользуемся методом bind() для привязки обработчика событий ко всем элементам <а>, имеющимся в документе, и затем создадим новые элементы <a>, эти новые элементы не будут иметь обработчиков событий, которые были в старых элементах, и будут вести себя иначе.

В библиотеке jQuery эта проблема решается с помощью «динамических событий». Чтобы задействовать динамические события, вместо методов bind() и unbind() следует использовать методы delegate() и undelegate().

Обычно метод delegate() вызывается относительно $(document), и ему передаются строка селектора, строка с типом события и функция обработчика, а он регистрирует внутренний обработчик в объекте документа или окна (или в любом другом элементе, находящемся в объекте jQuery). Когда событие указанного типа всплывет до этого внутреннего обработчика, он выяснит, соответствует ли целевой элемент события (элемент, в котором оно возникло) строке селектора, и вызовет указанную функцию обработчика. То есть чтобы обеспечить обработку события "mouseover" и в старых, и во вновь созданных элементах <a>, можно зарегистрировать обработчик, как показано ниже:

$(document).delegate("a", "mouseover", linkHandler);
или сначала применить метод bind() к статической части документа, а затем с помощью метода delegate() обработать динамически изменяемую часть:
// Статические обработчики событий для статических ссылок
$("a").bind("mouseover", linkHandler);

// Динамические обработчики событий для фрагментов документа,
// которые изменяются динамически
$(".dynamic").delegate("a", "mouseover", linkHandler);
Подобно тому, как метод bind() имеет версию с тремя аргументами, позволяющую указать значение свойства data объекта события, метод delegate() имеет версию с четырьмя аргументами, позволяющую то же самое. При использовании этой версии дополнительные данные следует передавать в третьем аргументе, а функцию обработчика – в четвертом.

Важно понимать, что динамические события основаны на механизме всплытия. К тому моменту, когда оно всплывет до объекта документа, оно может пройти через множество статических обработчиков. А если какой-либо из этих обработчиков вызовет метод cancelBubble() объекта event, динамический обработчик так и не будет вызван.

Объект jQuery имеет метод live(), который также можно использовать для регистрации динамических обработчиков событий. Метод live() устроен немного сложнее, чем метод delegate(), но он, как и метод bind(), имеет версии с двумя и тремя аргументами, которые чаще всего используются на практике. Два вызова метода delegate(), показанные выше, можно было бы заменить следующими вызовами метода live():

$("a").live("mouseover", linkHandler);
$("a", $(".dynamic")).live("mouseover", linkHandler);
Когда вызывается метод live(), элементы, находящиеся в объекте jQuery), в действительности никак не используются. Что имеет значение, так это строка селектора и объект контекста (первый и второй аргументы функции $(), использовавшиеся при создании объекта jQuery. Эти значения доступны в виде свойств selector и context объектов jQuery (раздел 19.1.2). Обычно функция $() вызывается с единственным аргументом, а роль контекста в этом случае играет текущий документ. То есть при использовании объекта x типа jQuery следующие две строки можно считать эквивалентными:
x.live(type,handler);
$(x.context).delegate(x.selector, type, handler);
Для удаления динамических обработчиков событий используются методы die() и undelegate(). Метод die() может вызываться с одним или с двумя аргументами. Если методу передать единственный аргумент, определяющий тип события, он удалит все динамические обработчики событий, соответствующие селектору и типу событий. А если передать тип события и функцию обработчика, он удалит только указанный обработчик. Например:
$('a').die('mouseover'); // Удалит все динамические обработчики события mouseover из элементов <a>
$('a').die('mouseover', linkHandler); // Удалит только указанный динамический обработчик
Метод undelegate() действует аналогично методу die(), но более явно отделяет контекст (элементы, в которых был зарегистрирован внутренний обработчик) и строку селектора. Вызовы метода die() выше можно было заменить вызовами метода undelegate(), ак показано ниже:
$(document).undelegate('a'); // Удалит все динамические обработчики из элементов <a>
$(document).undelegate('a', 'mouseover'); // Удалит динамические обработчики события mouseover
$(document).undelegate('a', 'mouseover', linkHandler); // Указанный обработчик
Наконец, метод undelegate() может также вызываться вообще без аргументов. В этом случае он удаляет все динамические обработчики, привязанные к выбранным элементам.

содержание 19.5. Анимационные эффекты содержание

В главе 16 демонстрировалось, как можно управлять стилями CSS в элементах документа. Например, устанавливая CSS-свойство visibility, можно заставлять элементы появляться и скрываться. В разделе 16.3.1 было показано, как, управляя стилями CSS, можно воспроизводить анимационные эффекты. Например, вместо того, чтобы просто сделать элемент невидимым, можно постепенно уменьшать значение его свойства opacity в течение половины секунды и заставить его исчезать плавно. Подобные визуальные эффекты оставляют у пользователей более приятные впечатления, и библиотека jQuery упрощает их реализацию. Объект jQuery определяет методы воспроизведения основных визуальных эффектов, такие как fadeIn() и fadeOut(). Кроме них он определяет также метод animate(), позволяющий воспроизводить более сложные эффекты. В следующих подразделах описываются и методы воспроизведения простых эффектов, и более сложный универсальный метод animate(). Однако для начала познакомимся с некоторыми общими особенностями механизма анимационных эффектов в библиотеке jQuery. Каждый анимационный эффект имеет продолжительность, которая определяет, как долго должен продолжаться эффект. Продолжительность можно указать в виде числа миллисекунд или в виде строки. Строка "fast" означает 200 миллисекунд. Строка "slow" означает 600 миллисекунд. Если указать строку, которая не будет распознана библиотекой jQuery, по умолчанию будет использована продолжительность 400 миллисекунд. Имеется возможность определять новые названия, обозначающие продолжительность, добавляя новые отображения строк в числа в объект jQuery.fx.speeds:

jQuery.fx.speeds["medium-fast"] = 300;
jQuery.fx.speeds["medium-slow"] = 500;
Методы воспроизведения эффектов объекта jQuery обычно принимают продолжительность в первом необязательном аргументе. Если опустить этот аргумент, по умолчанию продолжительность будет составлять 400 миллисекунд. Однако некоторые методы, не получив аргумент с продолжительностью, выполняют операцию немедленно, без анимационного эффекта:

$("#message").fadeIn(); // Эффект проявления будет длиться 400 мсек
$("#message").fadeOut("fast"); // Эффект растворения будет длиться 200 мсек
Эффекты в библиотеке jQuery воспроизводятся асинхронно. Когда производится вызов метода анимационного эффекта, такого как fadeIn(),
, он сразу же возвращает управление, а воспроизведение эффекта выполняется «в фоновом режиме». Поскольку методы анимационных эффектов возвращают управление до того, как эффект завершится, многие из них принимают во втором аргументе (также необязательном) функцию, которая будет вызвана по окончании воспроизведения эффекта. Этой функции не передается никаких аргументов, но ссылка this
в ней будет указывать на элемент документа, к которому применялся эффект. Функция будет вызвана по одному разу для каждого выбранного элемента:
// Быстро проявить элемент, а когда он станет видимым, вывести в нем текст.
$("#message").fadeIn("fast", function() { $(this).text("Hello World"); });
Передача функции обратного вызова методу воспроизведения эффекта позволяет выполнять действия по его окончании. Однако в этом нет необходимости, когда требуется просто последовательно воспроизвести несколько эффектов. По умолчанию библиотека jQuery ставит анимационные эффекты в очередь (в разделе 19.5.2.2 демонстрируется, как изменить это поведение по умолчанию). Если вызвать метод анимационного эффекта относительно элемента, для которого уже воспроизводится анимационный эффект, воспроизведение нового эффекта не начнется немедленно, а будет отложено до окончания воспроизведения текущего эффекта. Например, можно заставить элемент «моргать», пока он не проявится окончательно:
$("#blinker").fadeIn(100).fadeOut(100).fadeIn(100).fadeOut(100).fadeIn();
Методы анимационных эффектов объекта jQuery принимают необязательные аргументы, определяющие продолжительность и функцию обратного вызова. Однако этим методам можно также передавать объект, свойства которого определяют параметры эффектов:
// Передать продолжительность и функцию не в отдельных аргументах, а в свойствах объекта
$("#message").fadeIn({
    duration: "fast",
    complete: function() { $(this).text("Hello World"); }
});
Этот прием с передачей объекта обычно применяется при использовании универсального метода animate(), но он также может применяться и при работе с методами простых анимационных эффектов. Использование объекта позволяет также определять и другие, расширенные параметры, такие как параметры управления очередью и переходами эффектов. Доступные параметры будут описаны в разделе 19.5.2.2.

Отключение анимационных эффектов

Анимационные эффекты стали нормой на многих веб-сайтах, но они нравятся не всем пользователям: некоторые считают их раздражающими, а кто-то даже может испытывать неприятные ощущения. Пользователи с ограниченными возможностями могут обнаружить, что анимационные эффекты затрудняют использование вспомогательных технологий, таких как программы чтения с экрана, а владельцы устаревших компьютеров будут ощущать нехватку вычислительных мощностей. В качестве жеста уважения к своим пользователям вы должны стараться использовать более простые анимационные эффекты и в небольшом количестве, а также предоставлять возможность полностью отключать их. Библиотека jQuery дает простую возможность отключить сразу все эффекты: достаточно просто установить свойство jQuery.fx.off в значение true. В результате продолжительность всех эффектов будет установлена равной 0 миллисекунд, что заставит их выполняться мгновенно, без анимации.

Чтобы дать пользователям возможность отключать анимационные эффекты, можно включить в сценарий следующий фрагмент:

$(".stopmoving").click(function() { jQuery.fx.off = true; });
Затем веб-дизайнер должен включить в страницу элемент с классом “stopmoving”, щелчок на котором будет отключать воспроизведение анимационных эффектов.

содержание 19.5.1. Простые эффекты

Библиотека jQuery реализует девять методов простых анимационных эффектов скрытия и отображения элементов. Их можно разделить на три группы по типам воспроизводимых ими эффектов:

fadeIn(), fadeOut(), fadeTo()
Это самые простые эффекты: методы fadeIn() и fadeOut() просто управляют CSS-свойством opacity, чтобы скрыть элемент или сделать его видимым. Оба принимают необязательные аргументы, определяющие продолжительность и функцию обратного вызова. Метод fadeTo() несколько отличается: он принимает аргумент, определяющий конечное значение непрозрачности и плавно изменяет текущее значение непрозрачности элемента до указанного. В первом обязательном аргументе методу fadeTo() передается продолжительность (или объект с параметрами), а во втором обязательном аргументе – конечное значение непрозрачности. Функция обратного вызова передается в третьем необязательном аргументе.
show(), hide(), toggle())

Метод fadeOut(), описанный выше, делает элемент невидимым, но сохраняет занимаемую им область в документе. Метод hide(), напротив, удаляет элемент из потока документа, как если бы его CSS-свойство display было установлено в значение попе. При вызове без аргументов методы hide() и show() просто немедленно скрывают и отображают выбранные элементы. Однако при вызове с аргументом, определяющим продолжительность (или объект с параметрами), они воспроизводят анимационный эффект скрытия или появления. Ме; тод hide() уменьшает ширину и высоту элемента до 0 и одновременно уменьшает до 0 непрозрачность элемента. Метод show() выполняет обратные действия.

Метод toggle() изменяет состояние видимости элементов: для скрытых элементов он вызывает метод show(), а для видимых – метод hide(). Как и при работе с методами show() и hide(), чтобы воспроизвести анимационный эффект, методу toggle() необходимо передать продолжительность или объект с параметрами. Передача значения true методу toggle() эквивалентна вызову метода show() без аргументов, а передача значения false – вызову метода hide() без аргументов. Обратите также внимание, что если передать методу toggle() одну или более функций, он зарегистрирует обработчики событий, как описывалось в разделе 19.4.1.

slideDown(), slideUp(), slideToggle()
Это самые простые эффекты: методы fadeIn() и fadeOut() просто управляют CSS-свойством opacity, чтобы скрыть элемент или сделать его видимым. Оба принимают необязательные аргументы, определяющие продолжительность и функцию обратного вызова. Метод fadeTo() несколько отличается: он принимает аргумент, определяющий конечное значение непрозрачности и плавно изменяет текущее значение непрозрачности элемента до указанного. В первом обязательном аргументе методу fadeTo() передается продолжительность (или объект с параметрами), а во втором обязательном аргументе – конечное значение непрозрачности. Функция обратного вызова передается в третьем необязательном аргументе.

slideDown(), slideUpQ, slideToggle()

Метод slideUp() скрывает выбранные элементы в объекте jQuery, постепенно уменьшая их высоту до 0, и затем устанавливает CSS-свойство display в значение "none”. Метод slideDown() выполняет противоположные действия, чтобы сделать скрытый элемент видимым. Метод slideToggle() переключает состояние видимости элементов, используя методы slideUp() и slideDown(). Каждый из этих трех методов принимает необязательные аргументы, определяющие продолжительность и функцию обратного вызова (или объект с параметрами).
Следующий пример демонстрирует использование методов из всех трех групп. Имейте в виду, что по умолчанию библиотека jQuery ставит анимационные эффекты в очередь, что обеспечивает их выполнение по очереди:
// Растворить все элементы, затем показать их, затем свернуть и развернуть
$("img").fadeOut().show(300).slideUp().slideToggle();

Различные расширения библиотеки jQuery (раздел 19.9) добавляют в нее дополнительные анимационные эффекты. Наиболее полный набор эффектов включает библиотека jQuery UI (раздел 19.10).

содержание 19.5.2. Реализация собственных анимационных эффектов

Метод animate() позволяет воспроизводить более сложные анимационные эффекты, чем методы простых эффектов. Первый аргумент метода animate() определяет воспроизводимый эффект, а остальные аргументы – параметры этого эффекта. Первый аргумент является обязательным: это должен быть объект, свойства которого задают CSS-атрибуты и их конечные значения. Метод animate() плавно изменяет CSS-свойства всех элементов от текущих их значений до указанного конечного значения. То есть эффект, воспроизводимый описанным выше методом slideUp(), можно, например, реализовать, как показано ниже:

// Уменьшить высоту всех изображений до О
$("img").animate({ height: 0 });
Во втором необязательном аргументе методу animate() можно передать объект с параметрами эффекта:
$("#sprite").animate({
   opacity: .25, // Animate opacity to .25
  font-size: 10 // Animate font size to 10 pixels
}, {
  duration: 500, // Animation lasts 1/2 second
  complete: function() { // Call this function when done
    this.text("Goodbye"); // Change element text .
  }
});
Вместо объекта с параметрами во втором аргументе метод animate() позволяет также передать три наиболее часто используемых параметра в виде отдельных аргументов. Во втором аргументе можно передать продолжительность (в виде числа или строки), в третьем аргументе – имя функции, выполняющей переходы (подробнее об этой функции рассказывается чуть ниже.) И в четвертом аргументе – функцию обратного вызова.

В самом общем случае метод animate() принимает два аргумента с объектами. Первый определяет CSS-атрибуты, которые будут изменяться, а второй – параметры их изменения. Чтобы полностью понять, как выполняются анимационные эффекты в библиотеке jQuery, необходимо поближе познакомиться с обоими объектами.

содержание 19.5.2.1. Объект, определяющий изменяемые атрибуты

Первым аргументом метода animate() должен быть объект. Имена свойств этого объекта должны совпадать с именами CSS-атрибутов, а значения этих свойств должны определять конечные значения атрибутов, которые должны быть получены к окончанию эффекта. Участвовать в анимационном эффекте могут только атрибуты с числовыми значениями: невозможно реализовать плавное изменение значения цвета, шрифта или свойств-перечислений, таких как display. Если значением свойства является число, подразумевается, что оно измеряется в пикселах. Если значение является строкой, в ней можно указать единицы измерения. Если единицы измерения отсутствуют, опять же предполагается, что значение измеряется в пикселах. Чтобы указать относительные значения, в строковые значения следует добавить префикс: "+="  – для увеличения и "−=" – для уменьшения значения. Например:

$("p").animate({
  "margin-left": "+=.5in", // Increase paragraph indent
  opacity: "-=.1" // And decrease their opacity
});
Обратите внимание на кавычки, окружающие имя свойства "margin-left" в приведенном примере литерала объекта. Наличие дефиса в имени этого свойства делает его недопустимым идентификатором в языке JavaScript, поэтому в подобных случаях следует использовать кавычки. Разумеется, библиотека jQuery позволяет также использовать альтернативные имена со смешанным регистром символов, такие как marginLeft,.

Помимо числовых значений (с необязательными единицами измерения и префиксами "+=" и "−=") существует еще три значения, которые можно использовать в объектах, определяющих изменяемые свойства. Значение "hide" сохранит текущее значение указанного свойства и затем плавно изменит его до 0. Значение "show" плавно изменит значение CSS-свойства до его сохраненного значения. При использовании значения "show" библиотека jQuery вызовет метод show() по завершении эффекта. А при использовании значения "hide" она вызовет метод hide(). Можно также использовать значение "toggle", которое обеспечит увеличение ("show") или уменьшение ("hide") значения атрибута в зависимости от его текущего состояния. Например, ниже показано, как можно реализовать эффект "slideRight” сворачивания вправо (подобный эффекту сворачивания вверх, воспроизводимому методом slideUp(), но изменяющий ширину элемента):

$("img").animate({
    width: "hide",
    borderLeft: "hide",
    borderRight: "hide",
    paddingLeft: "hide",
    paddingRight: "hide"
});
Замените значения свойств на "show" или "toggle", чтобы получить эффект разворачивания по горизонтали, аналогичные тем, что воспроизводятся методами slideDown() и slideToggle()..

содержание 19.5.2.2. Объект с параметрами анимационного эффекта

Во втором необязательном аргументе методу animate() может передаваться объект с параметрами анимационного эффекта. Вы уже знакомы с двумя наиболее важными параметрами. Значением свойства duration может быть число, определяющее длительность эффекта в миллисекундах, а также строка "fast", "slow" или любая другая, объявленная в свойстве jQuery.fx.speeds.

Другим параметром, с которым вы уже встречались, является свойство complete: оно определяет функцию, которая должна быть вызвана по окончании эффекта. Похожее свойство step определяет функцию, которая должна вызываться для каждого шага или кадра анимации. Элемент, к которому применяется эффект, передается этой функции в виде значения ссылки this, а текущее значение изменяемого свойства – в первом аргументе.

Свойство queue объекта с параметрами определяет – должен ли данный эффект ставиться в очередь. То есть должно ли откладываться воспроизведение данного эффекта до окончания всех предыдущих эффектов. По умолчанию все анимационные эффекты ставятся в очередь. Если свойству queue присвоить значение false, эффект не будет поставлен в очередь. Воспроизведение таких внеочередных эффектов начинается немедленно. Последующие анимационные эффекты, которые ставятся в очередь, не будут ждать завершения внеочередных эффектов. Рассмотрим следующий пример:

$("img").fadeIn(500)
    .animate({"width":"+=100"}, {queue:false, duration:1000})
    .fadeOut(500);
Эффекты, запускаемые методами fadeIn() и fadeOut(), будут поставлены в очередь, а эффект, запускаемый вызовом метода animate() (эффект изменения значения свойства width на протяжении 1000 миллисекунд) – нет. Изменение ширины начнется одновременно с эффектом fadeIn(). Эффект fadeOut() начнется сразу после окончания эффекта fadeIn(): он не будет ждать, пока завершится эффект, изменяющий ширину элемента.

Функции переходов

В самом простом случае воспроизведение анимационного эффекта заключается в линейном изменении во времени значения свойства. Например, через 100 миллисекунд после начала эффекта, длительность которого составляет 400 миллисекунд, величина изменения значения свойства составит 25%. То есть при линейном изменении свойства opacity от 1,0 до 0,0 (как, например, при использовании метода fadeOut()) в этот момент оно должно иметь значение 0,75. Однако, как оказывается, визуальные эффекты дают более глубокие впечатления, если они выполняются нелинейно. Поэтому библиотека jQuery предусматривает возможность использования «функции перехода», которая отображает проценты от общего времени выполнения эффекта в проценты от конечного значения свойства. Библиотека jQuery передает функции перехода значение времени в диапазоне от 0 до 1, а она должна вернуть другое значение в диапазоне от 0 до 1, исходя из которого библиотека jQuery вычислит значение CSS-свойства, опираясь на его вычисленное значение. Конечно, в общем случае ожидается, что функции переходов будут возвращать значение 0, когда им передается значение 0, и 1, когда им передается значение 1, но между этими двумя значениями они могут быть нелинейными, что будет проявляться в ускорении и замедлении анимационных эффектов.

По умолчанию в библиотеке jQuery используется синусоидальная функция перехода: эффект сначала протекает медленно, затем ускоряется, и затем опять замедляется при приближении к конечному значению. Функции переходов в библиотеке jQuery имеют имена. Функция по умолчанию называется "swing", а линейная функция называется "linear". Вы можете добавлять свои функции переходов в объект jQuery.easing:

jQuery.easing["squareroot"] = Math.sqrt;

Библиотека jQuery UI и расширение, известное как "the jQuery Easing Plugin", определяют весьма исчерпывающий набор дополнительных функций переходов.

Остальные параметры анимационных эффектов имеют отношение к функциям переходов. Свойство easing объекта с параметрами определяет имя функции перехода. По умолчанию библиотека jQuery использует синусоидальную функцию с именем "swing". Если необходимо, чтобы анимационный эффект воспроизводился линейно, следует использовать параметры, как показано ниже:
$("img").animate({"width":"+=100"}, {duration: 500, easing:"linear"});
Напомню, что параметры duration, easing и complete можно также передавать методу animate() в виде отдельных аргументов. То есть предыдущий анимационный эффект можно запустить так:
$("img").animate({"width":"+=100"}, 500, "linear");
Наконец, механизм воспроизведения анимационных эффектов в библиотеке jQuery позволяет даже указывать для разных CSS-свойств разные функции переходов. Сделать это можно двумя разными способами, как показано в следующем примере:

// Требуется скрыть изображения, подобно методу hide(), при этом изменение
// размеров изображения должно протекать линейно, а изменение непрозрачности
// с применением функции перехода "swing" по умолчанию

// Первый способ:
// Использовать параметр specialEasing, чтобы указать другую функцию перехода
$("img").animate({ width:"hide", height:"hide", opacity:"hide" },
        { specialEasing: { width: "linear", height: "linear" }});

// Второй способ:
// Передать массивы [целевое значение, функция перехода] в объекте,
// который передается в первом аргументе..
$("img").animate({
    width: ["hide", "linear"], height: ["hide", "linear"], opacity:"hide"
});

содержание 19.5.3. Отмена, задержка и постановка эффектов в очередь

В библиотеке jQuery определяется еще несколько методов, имеющих отношение к анимационным эффектам и очередям, которые необходимо знать. Первым из них является метод stop(): он останавливает воспроизведение текущего анимационного эффекта для выбранных элементов. Метод stop() принимает два необязательных логических аргумента. Если в первом аргументе передать true, очередь анимационных эффектов для выбранных элементов будет очищена: т. е. вместе с текущим эффектом будут отменены все остальные эффекты, находящиеся в очереди. По умолчанию этот аргумент принимает значение false: если аргумент не указан, эффекты, находящиеся в очереди, не отменяются. Второй аргумент определяет, должны ли изменяемые CSS-свойства остаться в текущем состоянии или им должны быть присвоены конечные значения. Значение true во втором аргументе заставляет присвоить им конечные значения. Значение false (или отсутствие аргумента) оставляет текущие значения CSS-свойств. Когда анимационные эффекты запускаются по событиям, возникающим в результате действий пользователя, может потребоваться отменить все текущие и запланированные анимационные эффекты, прежде чем запустить новые. Например:

// Сделать изображения непрозрачными, когда указатель мыши находится над ними
// Не забудьте отменить все запланированные анимационные эффекты по событиям мыши!
$("img").bind({
    mouseover: function() { $(this).stop().fadeTo(300, 1.0); },
    mouseout: function() { $(this).stop().fadeTo(300, 0.5); }
});
Второй метод, связанный с анимацией, который мы рассмотрим здесь, – это метод delay(). Он просто добавляет задержку в очередь эффектов. В первом аргументе он принимает задержку в миллисекундах (или строку), а во втором необязательном аргументе – имя очереди (указывать второй аргумент обычно не требуется: об именах очередей будет рассказываться ниже). Метод delay() можно использовать в составных анимационных эффектах, как показано в этом примере:
// Быстро растворить элемент до половины, подождать, а затем свернуть его
$("img").fadeTo(100, 0.5).delay(200).slideUp();
В приведённом выше примере, где применялся метод stop(), были использованы обработчики событий "mouseover" и "mouseout" для плавного изменения непрозрачности изображений. Этот пример можно усовершенствовать, если добавить в него короткую задержку перед запуском анимационного эффекта. При таком подходе, если указатель мыши быстро пересекает изображение без остановки, никакого анимационного эффекта не возникает:
$("img").bind({
    mouseover: function() { $(this).stop(true).delay(100).fadeTo(300, 1.0); },
    mouseout: function() { $(this).stop(true).fadeTo(300, 0.5); }
});
Последняя группа методов, с которыми мы познакомимся, предоставляют низкоуровневый доступ к механизму очередей в библиотеке jQuery. Очереди в библиотеке jQuery реализованы в виде списков функций, которые выполняются в порядке их следования. Каждая очередь связана с определенным элементом документа (или с объектом Document или Window), и все очереди в элементах не зависят друг от друга. Добавить новую функцию в очередь (англ. queue) можно с помощью метода queue(). Когда функция достигнет головы очереди, она будет автоматически исключена из очереди и вызвана. Внутри этой функции ключевое слово this ссылается на элемент, с которым связана данная очередь. В единственном аргументе функции будет передана другая функция. Когда функция из очереди завершит свою работу, она должна вызвать переданную ей функцию; тем самым она запустит следующую операцию из очереди. Если эта функция не будет вызвана, обработка очереди будет заморожена и оставшиеся в ней функции никогда не будут вызваны.

Мы уже знаем, что методам анимационных эффектов можно передавать функции обратного вызова для выполнения некоторых действий по завершении воспроизведения эффекта. Того же эффекта можно добиться, поместив эту функцию в очередь:

// Проявить элемент, подождать, записать в него текст, и изменить его рамку
$("#message").fadeIn().delay(200).queue(function(next) {
    $(this).text("Hello World"); // Вывести текст
    next(); // Запустить следующую функцию в очереди
}).animate({borderWidth: "+=10px;"}); // Увеличить толщину рамки
Аргумент с функцией, который передается функции, помещаемой в очередь, – это новая особенность, появившаяся в версии jQuery 1.4. При использовании более ранних версий библиотеки функции в очереди извлекали следующую функцию «вручную», вызывая метод dequeue() (англ. исключать из очереди):
$(this).dequeue(); // Вместо next()
Если очередь пуста, метод dequeue() ничего не делает. В противном случае он удаляет функцию, находящуюся в голове очереди, и вызывает ее, устанавливая значение ссылки this и передавая функцию, описанную выше.

Кроме того, существует еще несколько методов управления очередью вручную. Метод clearQueue() очищает очередь. Если вместо единственной функции передать методу queue() массив функций, он заменит текущую очередь новым массивом функций. А вызов метода queue() без аргумента вернет текущую очередь в виде массива. Кроме того, библиотека jQuery определяет версии методов queue() и dequeue() в виде вспомогательных функций. Например, если потребуется добавить функцию f в очередь элемента e, сделать это можно будет с помощью метода или функции:

$(e).queue(f); // Создать объект jQuery, хранящий е. и вызвать метод queue
jQuery.queue(e,f); // Просто вызвать вспомогательную функцию
Наконец, обратите внимание, что методы queue(), dequeue() и clearQueue() принимают необязательный первый аргумент с именем очереди. Методы анимационных эффектов используют очередь с именем "fx", и именно эта очередь используется по умолчанию, если имя очереди не указано явно. Механизм очередей в библиотеке jQuery с успехом можно использовать для выполнения асинхронных операций в определенной последовательности: вместо того чтобы передавать функцию обратного вызова каждой асинхронной операции, чтобы она запускала следующую функцию в последовательности, для управления последовательностью можно использовать очередь. Просто используйте имя очереди, отличное от "fx", и не забывайте, что функции в очереди не вызываются автоматически. Чтобы запустить первую функцию в очереди, необходимо явно вызвать метод dequeue(), а по завершении каждая операция должна запускать следующую.

содержание 19.6. Реализация Ajax в библиотеке jQuery содержание

Ajax – популярное название комплекса приемов разработки веб-приложений, в которых применяются возможности использования протокола HTTP (Глава 18 ) для загрузки данных по мере необходимости без перезагрузки страниц. Приемы Ajax оказались настолько полезны в современных веб-приложениях, что в библиотеку jQuery были включены вспомогательные функции, реализующие и упрощающие их использование. Библиотека jQuery определяет один высокоуровневый вспомогательный метод и четыре высокоуровневые вспомогательные функции. Все они основаны на одной низкоуровневой функции, jQuery.ajax(). В следующих подразделах мы сначала познакомимся с высокоуровневыми утилитами, а затем детально рассмотрим функцию jQuery.ajax(). Понимание принципов действия функции jQuery.ajax() совершенно необходимо, даже если вам никогда не придется использовать ее явно, чтобы до конца понять, как действуют высокоуровневые утилиты.

содержание 19.6.1. Метод load()

Метод load() является самой простой из всех утилит в библиотеке jQuery: он принимает URL-адрес, асинхронно загружает его содержимое и затем вставляет это содержимое в каждый из выбранных элементов, заменяя любое имеющееся содержимое. Например:

// Загружать и отображать последнюю информацию о состоянии каждые 60 сек.
setInterval(function() { $("#stats").load("status_report.html"); }, 60000);

Коды состояния Ajax, генерируемые библиотекой jQuery

Все утилиты поддержки архитектуры Ajax в библиотеке jQuery, включая метод load(), вызывают функции обратного вызова, чтобы асинхронно уведомить приложение об успехе или неудаче. Во втором аргументе этим функциям обратного вызова передается строка с одним из следующих значений: "success"

"success" "notmodified" "error" "timeout" "parsererror"

Мы уже встречались с методом load() в разделе 19.4.1, где использовали его для регистрации обработчика события "load". Если в первом аргументе этому методу передать функцию, а не строку, он будет играть роль метода регистрации обработчика события, а не метода поддержки архитектуры Ajax.

Если вам потребуется просто отобразить фрагмент загруженного документа, добавьте в конец URL-адреса пробел и селектор jQuery. Когда содержимое URL-адреса будет загружено, указанный селектор будет использован для выбора фрагмента загруженного HTML-документа и его отображения:

// Загрузить и отобразить температуру из документа со сводкой погоды
$('#temp').load("weather_report.html #temperature");
Обратите внимание, что селектор в конце этого URL-адреса похож на идентификатор фрагмента (части URL-адресов, начинающиеся с символа решетки, описывались в разделе 14.2). Пробел в данном случае является обязательной частью, если необходимо, чтобы библиотека jQuery вставила лишь выбранный фрагмент (или фрагменты) загруженного документа.

В дополнение к обязательному URL-адресу метод load() принимает два необязательных аргумента. Первый – данные, добавляемые в URL-адрес или отправляемые вместе с запросом. Если в этом аргументе передать строку, она будет добавлена в конец URL (при необходимости после ?? или &). Если передать объект, он будет преобразован в строку пар имя/значение, разделенных амперсандами, и отправлен вместе с запросом (описание особенностей преобразования объекта в строку для использования в составе запроса Ajax приводится во врезке в разделе 19.6.2.2 ). Обычно метод load() выполняет HTTP-запрос методом GET, но, если передать объект с данными, будет выполнен запрос методом POST. Например:

// Загрузить сводку погоды для населенного пункта с указанным почтовым индексом
$('#temp').load("us_weather_report.html", "zipcode=02134");

// Здесь данные передаются в виде объекта, в котором дополнительно указывается,
// что температура должна возвращаться в градусах по шкале Фаренгейта
$('#temp').load("us_weather_report.html", { zipcode:02134, units:'F' });
В другом необязательном аргументе методу load() можно передать функцию, которая будет вызвана в случае завершения Ajax-запроса, успешного или нет, и (в случае успеха) после того, как содержимое URL-адреса будет загружено и вставлено в выбранные элементы. Если методу не передаются никакие дополнительные данные, эту функцию обратного вызова можно передать во втором аргументе. Иначе она должна передаваться в третьем аргументе. Указанная функция будет вызвана как метод для каждого элемента, находящегося в объекте jQuery, и ей будет передано три аргумента: полное содержимое, загруженное с указанного URL-адреса, строка с кодом состояния и объект XMLHttpRequest, использовавшийся для загрузки содержимого. Аргумент с кодом состояния – это код состояния, созданный библиотекой jQuery, а не возвращаемый протоколом HTTP, и он может быть строкой, такой как "success", "error" или "timeout".

содержание 19.6.2. Вспомогательные функции поддержки Ajax

Другие высокоуровневые утилиты поддержки архитектуры Ajax в библиотеке jQuery являются функциями, а не методами и вызываются относительно глобального имени jQuery или $, а не относительно объекта с выбранными элементами. Функция jQuery.getScript() загружает и выполняет файлы со сценариями на языке JavaScript. Функция jQuery.getJSON(). загружает содержимое URL и разбирает его как текст в формате JSON, а получившийся в результате объект передает указанной функции обратного вызова. Обе эти функции вызывают функцию jQuery.get(), которая является более универсальной функцией загрузки данных из указанного URL-адреса. Наконец, функция jQuery.post() действует подобно функции jQuery.get(), но выполняет HTTP-запрос методом POST, а не GET. Как и метод load(), все эти функции выполняются асинхронно: они возвращают управление еще до того, как будут загружены какие-либо данные, и извещают программу о результатах посредством указанной функции обратного вызова.

содержание 19.6.2.1. JQuery.getScript()

Функция jQuery.getScript(). принимает в первом аргументе URL-адрес файла со сценарием на языке JavaScript. Она асинхронно загружает и выполняет этот сценарий в глобальной области видимости. Выполняться могут сценарии как общего происхождения с документом, так и сторонние:

// Динамически загрузить сценарий с некоторого другого сервера
jQuery.getScript("http://example.com/js/widget.js");
Во втором аргументе можно передать функцию обратного вызова, и в этом случае библиотека jQuery вызовет ее сразу после того, как загруженный сценарий будет выполнен.
// Загрузить библиотеку и воспользоваться ею после загрузки
jQuery.getScript("js/jquery.my_plugin.js", function() {
    $('div').my_plugin(); // Воспользоваться загруженной библиотекой
});
Для получения текста сценария, который должен быть выполнен, функция jQuery.getScript() обычно использует объект XMLHttpRequest. Но для выполнения междоменных запросов (когда сценарий поставляется сервером, отличным от того, откуда был получен текущий документ), библиотека jQuery использует элемент <script> (раздел 18.2). Если запрос удовлетворяет ограничениям политики общего происхождения, в первом аргументе функции обратного вызова передается текст сценария, во втором – код состояния "success" и в третьем – объект XMLHttpRequest, использовавшийся для получения текста сценария. Возвращаемым значением функции jQuery.getScript() в данном случае также является объект XMLHttpRequest. Для междоменных запросов, которые выполняются без участия объекта XMLHttpRequest, текст сценария не сохраняется. В этом случае в первом и третьем аргументах функции обратного вызова передается значение undefined, и возвращаемым значением функции jQuery.getScript() также является значение undefined. Функция обратного вызова, передаваемая функции jQuery.getScript(), вызывается только в случае успешного выполнения запроса. Если также необходимо получить извещение в случае ошибки, следует использовать низкоуровневую функцию jQuery.ajax(). To же относится и к трем другим вспомогательным функциям, описываемым в этом разделе.

содержание 19.6.2.2. jQuery.getJSON()

Функция jQuery.getJSON() подобна функции jQuery.getScript(): она загружает текст и затем обрабатывает его особым образом перед вызовом указанной функции обратного вызова. Функция jQuery.getJSON() не выполняет загруженный текст как сценарий, а выполняет синтаксический разбор этого текста как данных в формате JSON (используя функцию jQuery.parseJSON(): описывается в разделе 19.7 ). Функцию jQuery.getJSON() имеет смысл использовать, только когда ей передается функция обратного вызова. Если содержимое URL было благополучно загружено и разобрано, как данные в формате JSON, то полученный в результате объект передается функции обратного вызова в первом аргументе. Как и при использовании функции jQuery.getScript(), во втором и третьем аргументах передаются код состояния "success" и объект XMLHttpRequest:

// Допустим, что data.json содержит текст: '{"х":1,"у":2}'
jQuery.getJSON("data.json", function(data) {
// Здесь data – это объект {х:1, у:2}
});

Передача данных утилитам поддержки Ajax в библиотеке jQuery

Большинство методов поддержки архитектуры Ajax в библиотеке jQuery принимают аргумент (или параметр), определяющий данные для отправки на сервер вместе с URL. Обычно эти данные принимают вид строки, закодированной в формате URL, пар имя/значение, отделяющихся друг от друга символами амперсанда (этот формат представления данных известен, как MIME-тип "application/x-www-form-urlencoded". Его можно рассматривать как аналог формата JSON – формата представления простых JavaScript-объектов в виде строк). При выполнении HTTP-запросов методом GET эта строка с данными добавляется в конец URL-адреса запроса. При выполнении запросов методом POST она отправляется в теле запроса после отправки HTTP-заголовков.

Получить строку с данными в этом формате можно с помощью метода serialize() объекта jQuery, содержащего формы или элементы формы. Отправить, например, HTML-форму с помощью метода load() можно следующим образом:

$("#submit_button").click(function(event) {
    $(this.form).load( // Заменить форму, загрузив...
        this.form.action, // из указанного url
        $(this.form).serialize()); // с данными, добавленными в него
    event.preventDefault(); // Отменить отправку формы по умолч.
    this.disabled = "disabled"; // Предотвратить несколько попыток отправки
});
Если в аргументе (или параметре) передать функции поддержки архитектуры Ajax в библиотеке jQuery объект, а не строку, то библиотека jQuery по умолчанию (с исключениями, описываемыми ниже) автоматически преобразует объект в строку, вызвав функцию jQuery.param(). Эта вспомогательная функция интерпретирует свойства объекта как пары имя/значение и, например, преобразует объект {x:1,y:"hello"} в строку "x=1&y=hello".

В версии jQuery 1.4 функция jQuery.param() способна обрабатывать более сложные объекты. Если значение свойства объекта является массивом, для каждого элемента этого массива будет создана отдельная пара имя/значение, а к имени свойства будут добавлены квадратные скобки. Если значением свойства является объект, имена свойств этого вложенного объекта помещаются в квадратные скобки и добавляются к имени внешнего свойства. Например:

$.param({a:[1,2,3]}) // Вернет "a[]=1&a[]=2&a[]=3"
$.param({o:{x:1,y:true}}) // Вернет "o[x]=1&o[y]=true"
$.param({o:{x:{y:[1,2]}}}) // Вернет "o[x][y][]=1&o[x][y][]=2"
Для обратной совместимости с версией jQuery 1.3 и ниже во втором аргументе функции jQuery.param() можно передать значение true или установить параметр traditional в значение true. Это предотвратит использование расширенных возможностей сериализации свойств, значениями которых являются массивы или объекты.

Иногда бывает необходимо передать в теле POST-запроса объект Document (или какой-то другой объект, который не должен преобразовываться автоматически). В этом случае можно установить в параметре contentType тип данных и в параметре processData значение false и тем самым предотвратить передачу объекта с данными функции jQuery.param().

В отличие от jQuery.getScript(), функция jQuery.getJSON() принимает необязательный аргумент с данными, подобный тому, что передается методу load(). Если функции jQuery.getJSON()необходимо передать данные, они должны передаваться во втором аргументе, а функция обратного вызова – в третьем. Если дополнительные данные не требуются, функцию обратного вызова можно передать во втором аргументе. Если данные являются строкой, она будет добавлена в конец URL-адреса, вслед за символом ? или &. Если данные передаются в виде объекта, он будет преобразован в строку (как описывается во врезке) и добавлен в конец URL-адреса.

Если строка URL или данных, передаваемая функции jQuery.getJSON(), содержит последовательность символов "=?" в конце или перед амперсандом, она определяет запрос JSONP (описание формата JSONP приводится в разделе 18.2 ). Библиотека jQuery заменит знак вопроса именем функции обратного вызова, которая будет создана автоматически, и функция jQuery.getJSON() будет действовать, как если бы выполнялся запрос сценария, а не объекта в формате JSON. Этот прием не работает со статическими JSON-файлами данных: он может применяться только при наличии сценариев на стороне сервера, поддерживающих формат JSONP. Однако поскольку данные в формате JSONP обрабатываются как сценарии, для их получения допускается выполнять междоменные запросы.

содержание 19.6.2.3. jQuery.get() и jQuery.post()

Функции jQuery.get() и jQuery.post() загружают содержимое из указанного адреса URL, отправляя дополнительные данные, если они имеются, и передавая результат указанной функции обратного вызова. Функция jQuery.get() делает это, выполняя HTTP-запрос методом GET, а функция jQuery.post() – методом POST, но во всем остальном эти две вспомогательные функции совершенно идентичны. Обе они принимают те же три аргумента, что и функция jQuery.getJSON(): обязательный URL-адрес, необязательную строку или объект с данными и технически необязательную, но практически всегда используемую функцию обратного вызова. В первом аргументе функции обратного вызова передаются полученные данные, во втором – строка "success" и в третьем – объект XMLHttpRequest (если он использовался для выполнения запроса):

// Запросить текст с сервера и отобразить его в диалоге
jQuery.get("debug.txt", alert);
Помимо трех аргументов, описанных выше, эти две функции могут принимать четвертый необязательный аргумент (передается как третий аргумент, если дополнительные данные отсутствуют), который определяет тип запрашиваемых данных. Этот аргумент влияет на обработку полученных данных перед передачей их функции обратного вызова. Метод load() использует тип "html", jQuery.getScript() –тип "script", a jQuery.getJSON()  –тип "json". Однако функции jQuery.get() и jQuery.post() более гибкие, чем эти специализированные утилиты, и им можно указать любой из этих типов. Допустимые значения этого аргумента и особенности поведения библиотеки jQuery при его отсутствии описываются во врезке.

Типы данных, поддерживаемые реализацией Ajax в библиотеке jQuery

Функциям jQuery.get() и jQuery.post() допускается передавать любой из шести типов данных. Кроме того, как описывается ниже, любой из этих типов можно также передавать функции jQuery.ajax() в виде параметра dataType:

"text"

"html" "xml" "script" "json" "jsonp"

Если при вызове jQuery.get(), jQuery.post()) или jQuery.ajax() не указан ни один из этих типов, библиотека jQuery проверит заголовок "Content-Type" HTTP-ответа. Если этот заголовок включает подстроку "xml", функции обратного вызова будет передан XML-документ. Иначе, если заголовок включает подстроку "json", ответ будет разобран, как данные в формате JSON, и полученный объект будет передан функции обратного вызова. Иначе, если заголовок включает подстроку "JavaScript", ответ будет выполнен как сценарий. Иначе данные будут интерпретироваться как простой текст.

содержание 19.6.3. Функция jQuery.ajax()

Все утилиты поддержки архитектуры Ajax в библиотеке jQuery в конечном итоге вызывают jQuery.ajax()  – самую сложную функцию во всей библиотеке. Функция jQuery.ajax() принимает всего один аргумент: объект с параметрами, свойства которого определяют детали, касающиеся выполнения Ajax-запроса. Вызов jQuery.getScript(url,callback), например, эквивалентен следующему вызову функции jQuery.ajax():

jQuery.ajax({
    type: "GET", // Метод HTTP-запроса.
    url: url, // URL-адрес запрашиваемых данных.
    data: null, // Не добавлять дополнительные данные в URL.
    dataType: "script", // Выполнить ответ как сценарий.
    success: callback // Вызвать эту функцию по завершении.
});

Эти пять фундаментальных параметров можно также установить при использовании функций jQuery.get() и jQuery.post(). Однако при непосредственном использовании jQuery.ajax() имеется возможность указать большое количество других параметров. Все параметры (включая ранее представленные пять основных) детально описываются ниже.

Прежде чем погрузиться в описание параметров, обратите внимание, что имеется возможность определить значения по умолчанию любых из этих параметров, передав объект с параметрами функции jQuery.ajaxSetup()::

jQuery.ajaxSetup({
    timeout: 2000, // Прерывать все Ajax-запросы через 2 секунды
    cache: false // Игнорировать кэш браузера, добавляя время в URL
});

После выполнения программного кода, приведенного выше, указанные параметры timeout и cache будут действовать для всех Ajax-запросов (включая высокоуровневые утилиты, такие как jQuery.get() и load(), при вызове которых не указываются значения этих параметров.

В процессе знакомства с многочисленными параметрами и особенностями функций обратного вызова в следующих разделах может оказаться полезным еще раз ознакомиться с информацией во врезках, касающейся кодов состояния Ajax-запросов и типов данных в разделах 19.6.1 и 19.6.2.3.

Поддержка Ajax в версии jQuery 1.5

В версии jQuery 1.5, которая вышла, когда эта книга готовилась к печати, модуль поддержки архитектуры Ajax был полностью переписан, и в нем появилось несколько новых удобных особенностей. Самое важное, что функция jQuery.ajax() и все утилиты поддержки Ajax, описанные выше, теперь возвращают объект jqXHR. Этот объект имитирует прикладной интерфейс объекта XMLHttpRequest даже для запросов (например, выполняемых функцией $.getScript()), не использующих объект XMLHttpRequest. Кроме того, объект jqXHR определяет методы success() и error(), которые можно использовать для регистрации функций, вызываемых в случае успешного или неудачного завершения запроса. То есть вместо того чтобы передавать функцию обратного вызова функции jQuery.get(), например, ее можно зарегистрировать с помощью метода success()successQ объекта jqXHR, возвращаемого этой утилитой:

jQuery.get("data.txt")
   .success(function(data) { console.log("Got", data); })
    .success(function(data) { process(data); });

содержание 19.6.3.1. Часто используемые параметры

Ниже перечислены параметры, которые наиболее часто передаются функции jQuery.ajax():

type

Определяет метод HTTP-запроса. По умолчанию имеет значение "GET". Другим наиболее часто используемым значением является "POST". Допускается указывать также другие методы HTTP-запросов, такие как "DELETE" и "PUT", но они поддерживаются не всеми браузерами. Обратите внимание, что имя этого параметра может вводить в заблуждение: он не имеет никакого отношения к типу данных в запросе или ответе, и для него лучше подошло бы имя "method".

url

URL-адрес загружаемых данных. При выполнении GET-запросов параметр data добавляется в конец этого URL-адреса. Библиотека jQuery может автоматически добавлять параметры в строку URL при выполнении JSONP-запросов и когда параметр cache имеет значение false.

data

Данные, добавляемые в конец URL-адреса (для GET-запросов) или отправляемые в теле запроса(для POST-запросов). Может быть строкой или объектом. Объекты обычно преобразуются в строки, как описывалось во врезке в разделе 19.6.2.2, однако имеются некоторые исключения, которые приводятся в описании параметра processData.

dataType

Определяет тип ожидаемых данных в ответе и способ их обработки библиотекой jQuery. Допустимыми значениями являются "text", "html", "script", "json", "jsonp" и "xml". Суть этих значений описана во врезке в разделе 19.6.2.3. Этот параметр не имеет значения по умолчанию. Если он не указан, библиотека jQuery проверит заголовок "Content-Type" ответа, чтобы определить, что делать с полученными данными.

contentType

Определяет HTTP-заголовок "Content-Type" запроса. По умолчанию имеет значение "application/x-www-form-urlencoded", которое обычно используется HTML-формами и большинством серверных сценариев. Если вы установили параметр type в значение "POST" и собираетесь отправить в теле запроса простой текст или XML-документ, вам должны также установить этот параметр.

timeout

Предельное время ожидания в миллисекундах. Если этот параметр установлен и запрос не завершится в течение указанного времени, выполнение запроса прервется и будет вызвана функция обратного вызова error с кодом состояния "timeout". По умолчанию параметр timeout имеет значение 0, которое означает, что выполнение запроса будет продолжаться до его завершения и никогда не будет прервано.

cache

При выполнении GET-запросов, если этот параметр будет установлен в значение false, библиотека jQuery добавит параметр _= в строку URL или заменит существующий параметр с этим именем. В качестве значения этого параметра будет установлено текущее время (в виде количества миллисекунд). Это предотвратит использование кэша браузера, поскольку каждый раз, когда запрос будет выполняться, строка URL будет иной.

ifModified

Когда этот параметр имеет значение true, библиотека jQuery будет сохранять значения заголовков "Last-Modified" и "If-None-Match" ответов для каждого запрошенного URL-адреса и затем будет устанавливать эти заголовки во всех последующих запросах к тем же самым URL-адресам. Это предписывает серверу отправлять HTTP-ответ 304 "Not Modified", если содержимое по указанному URL-адресу не изменилось с момента последнего обращения. По умолчанию данный параметр не установлен и библиотека jQuery не сохраняет эти заголовки.

Библиотека jQuery преобразует HTTP-ответ 304 в код состояния "notmodif ied". Код "notmodified" не считается ошибкой и передается функции обратного вызова success вместо обычного кода состояния "success". To есть если вы устанавливаете параметр ifModified, вы также должны проверять код состояния в своей функции обратного вызова – если будет получен код состояния "notmodified", то первый аргумент функции (данные из ответа) будет иметь значение undefined. Обратите внимание, что в версии jQuery ниже 1.4 HTTP-ответ 304 интерпретировался как ошибка, и код состояния "notmodified" передавался функции обратного вызова error, а не success. Подробнее о кодах состояния рассказывается во врезке в разделе 19.6.1.

global

Этот параметр определяет, должна ли библиотека jQuery возбуждать события в ходе выполнения Ajax-запроса. По умолчанию имеет значение true. Присвойте этому параметру значение false, чтобы запретить все события, связанные с поддержкой архитектуры Ajax (полное описание событий приводится в разделе 19.6.4). Имя этого параметра несколько обескураживает: он имеет имя "global", потому что обычно библиотека jQuery возбуждает события глобально, а не в конкретном объекте.

содержание 19.6.3.2. Функции обратного вызова

Следующие параметры определяют функции, вызываемые на разных стадиях в ходе выполнения Ajax-запроса. С параметром success вы уже знакомы: это функция обратного вызова, которая передается методам, таким как jQuery.getJSON(). Обратите внимание, что библиотека jQuery также посылает извещения в ходе выполнения Ajax-запроса в виде событий (если параметр global не был установлен в значение false).

context

Этот параметр определяет объект, используемый в качестве контекста – значения ссылки this – для различных функций обратного вызова. Данный параметр не имеет значения по умолчанию, и если его не устанавливать, функции обратного вызова будут вызываться в контексте объекта с параметрами, в котором они определяются. Значение параметра context также воздействует на порядок возбуждения событий механизмом поддержки Ajax (раздел 19.6.4). Значением этого параметра должен быть объект Window, Document или Element, в котором могут возбуждаться события.

beforeSend

Этот параметр определяет функцию, которая должна вызываться перед отправкой Ajax-запроса на сервер. Первым аргументом этой функции передается объект XMLHttpRequest, а вторым – объект с параметрами запроса. Функция beforeSend дает программе возможность установить собственные HTTP-заголовки в объекте XMLHttpRequest. Если эта функция вернет false, выполнение Ajax-запроса будет прервано. Обратите внимание, что для выполнения междоменных запросов типов "script" и "jsonp" объект XMLHttpRequest не используется и функция, определяемая параметром beforeSend, не вызывается.

success

Этот параметр определяет функцию, которая должна вызываться в случае успешного выполнения Ajax-запроса. В первом аргументе ей передаются данные, отправленные сервером. Во втором аргументе – код состояния, сгенерированный библиотекой jQuery, и в третьем – объект XMLHttpRequest, использовавшийся для выполнения запроса. Как описывалось в разделе 19.6.2.3 , тип данных в первом аргументе зависит от значения параметра dataType или заголовка "Content-Type" в ответе сервера. Если данные имеют тип "xml", в первом аргументе передается объект Document. Если данные имеют тип "json" или "jsonp", в первом аргументе передается объект, полученный в результате разбора ответа сервера в формате JSON. Если данные имеют тип "script", ответом является текст загруженного сценария (однако к моменту вызова функции сценарий уже будет выполнен, поэтому в данном случае ответ обычно игнорируется). Для других типов ответ интерпретируется как простой текст, содержащийся в запрошенном ресурсе.

Код состояния во втором аргументе обычно является строкой "success". Но, если был установлен параметр ifModified, в этом аргументе может также передаваться строка "notmodified". В этом случае сервер не отправляет данные в ответе, и в первом аргументе будет передано значение undefined. Для выполнения междоменных запросов на получение данных типов "script" и "jsonp" используется элемент <script>, а не объект XMLHttpRequest, поэтому для таких запросов в третьем аргументе вместо объекта XMLHttpRequest будет передаваться значение undefined..

error

Этот параметр определяет функцию, которая должна вызываться в случае неудачи Ajax-запроса. В первом аргументе этой функции передается объект XMLHttpRequest запроса (если таковой использовался). Во втором аргументе – код состояния, сгенерированный библиотекой jQuery. Это может быть строка "error" – в случае ошибки протокола HTTP, "timeout" – в случае превышения времени ожидания и "parsererror" – в случае ошибки, возникшей в ходе разбора ответа сервера. Например, если XML-документ или объект в формате JSON будет сформирован неправильно, функция получит код состояния "parsererror". В этом случае в третьем аргументе функции error будет передан объект Error, представляющий исключение. Обратите внимание, что запросы с параметром dataType="script", возвращающие недопустимый программный код JavaScript, не вызывают ошибки. Любые ошибки в сценарии просто игнорируются и вместо функции error вызывается функция success.

complete

Этот параметр определяет функцию, которая должна вызываться по завершении Ajax-запроса. Каждый Ajax-запрос завершается либо успехом и вызывает функцию success, либо неудачей и вызывает функцию error. Библиотека jQuery вызывает функцию complete после вызова функции success или error. В первом аргументе функции complete передается объект XMLHttpRequest, а во втором – код состояния.

содержание 19.6.3.3. Редко используемые параметры и обработчики

Следующие параметры используются довольно редко. Некоторые из них являются параметрами, которые вам едва ли придется устанавливать, а другие определяют обработчики для тех, кому потребуется изменить порядок обработки Ajax- запросов, используемый в библиотеке jQuery по умолчанию.

async

Запросы HTTP по своей природе являются асинхронными. Однако объект XMLHttpRequest дает возможность заблокировать выполнение сценария до получения ответа. Если присвоить этому параметру значение false, библиотека jQuery будет блокировать работу с ценария. Данный параметр не влияет на значение, возвращаемое функцией jQuery.ajax(): она всегда возвращает объект XMLHttpRequest, если он используется. При выполнении синхронных запросов вы можете самостоятельно извлекать ответ сервера и код состояния HTTP из объекта XMLHttpRequest или определить функцию обратного вызова complete (как в случае асинхронных запросов), чтобы получить разобранный ответ и код состояния jQuery.

dataFilter

Этот параметр определяет функцию фильтрации или предварительной обработки данных, возвращаемых сервером. В первом аргументе ей будут передаваться необработанные данные, полученные от сервера (либо в виде строки, либо в виде объекта Document, при запросе XML-документа), а во втором аргументе – значение параметра dataFilter. Эта функция должна возвращать значение, которое будет использоваться вместо ответа сервера. Обратите внимание, что функция dataFilter вызывается перед разбором данных в формате JSON или перед выполнением сценария. Кроме того, отметьте, что dataFilter не вызывается при выполнении междоменных запросов данных типов "script" и "jsonp".

jsonp

Когда параметр dataType имеет значение "jsonp", значение параметра url или data обычно включает параметр строки запроса вида "jsonp=?". Если библиотека jQuery не обнаружит этот параметр в URL-адресе или в данных, она вставит его, используя значение параметра jsonp в качестве имени параметра в строке запроса. По умолчанию параметр jsonp имеет значение "callback". Присвойте ему другое значение, если сервер, поддерживающий обмен данными в формате JSONP, ожидает получить другое имя параметра в строке запроса и вы явно не указываете это имя в строке URL или в данных. Подробнее о формате JSONP рассказывается в разделе 18.2.

jsonpCallback

Для запросов с параметром dataType, имеющим значение "jsonp" (или "json", когда URL-адрес включает параметр строки запроса, такой как "jsonp=?"), библиотека jQuery будет изменять строку URL, подставляя вместо знака вопроса имя функции-обертки, которой сервер будет передавать данные. Обычно библиотека jQuery синтезирует уникальное имя функции, опираясь на текущее время. Присвойте этому параметру свое значение, если вам потребуется явно указать собственную функцию. Но имейте в виду, что в этом случае библиотека jQuery не будет вызывать функции обратного вызова success и complete и не будет возбуждать обычные события.

processData

Когда значением параметра data является объект (или объект передается во втором аргументе функции jQuery.get() и родственным ей функциям), библиотека jQuery обычно преобразует этот объект в строку в формате "application/x-www-form-urlencoded" (как описывается во врезке в разделе 19.6.2.2). Если потребуется предотвратить это преобразование (например, чтобы передать объект Document в теле POST-запроса), присвойте этому параметру значение false.

scriptCharset

Для междоменных запросов данных типов "script" и "jsonp", при выполнения которых используется элемент <script>, этот параметр определяет значение атрибута charset элемента. Он никак не влияет на обычные запросы, выполняемые с помощью объекта XMLHttpRequest.

traditional

В библиотеке jQuery версии 1.4 несколько изменился способ сериализации объектов с данными в строки формата "application/x-www-form-urlencoded" (подробности приводятся во врезке в разделе 19.6.2.2). Присвойте этому параметру значение true, если необходимо, чтобы библиотека jQuery использовала прежний порядок.

username, password

Если для выполнения запроса необходимо выполнить процедуру аутентификации пользователя, укажите имя пользователя и пароль в этих двух параметрах.

xhr

Этот параметр определяет фабричную функцию, создающую объект XMLHttpRequest. Она вызывается без аргументов и должна возвращать объект, реализующий прикладной программный интерфейс объекта XMLHttpRequest. Этот весьма низкоуровневый обработчик позволяет создавать собственные обертки вокруг объекта XMLHttpRequest и добавлять новые особенности или расширять его методы.

содержание 19.6.4. События в архитектуре Ajax

В разделе 19.6.3.2 говорилось, что функция jQuery.ajax() имеет четыре параметра, определяющие функции обратного вызова: bef oreSend, success, error и complete. Помимо вызова этих функций, функции поддержки архитектуры Ajax в библиотеке jQuery также возбуждают собственные события на каждой стадии выполнения запроса. В следующей таблице перечислены параметры, определяющие функции обратного вызова, и соответствующие им события:

Функция обратного вызова

beforeSend

success

error

complete

Тип события

" ajaxSend"

" ajaxSuccess"

" ajaxError"

" ajaxComplete"

" ajaxStarU

" ajaxStop"

Метод регистрации обработчика

ajaxSend()

ajaxSuccess()

ajaxError()

ajaxComplete()

ajaxStart()

ajaxStop()

Зарегистрировать обработчики этих событий можно с помощью метода bind() (раздел 19.4.4), используя строку с типом события из второй колонки, или с помощью методов из третьей колонки. Метод ajaxSuccess() и другие действуют точно так же, как clickQ, mouseoverQ и другие простые методы регистрации событий, о которых рассказывалось в разделе 19.4.1.

Поскольку события, генерируемые реализацией архитектуры Ajax, являются нестандартными и генерируются самой библиотекой jQuery, а не браузером, объект Event, передаваемый обработчикам, не содержит сколько-нибудь полезной информации. Однако вместе со всеми событиями – "ajaxSend", "ajaxSuccess", "ajaxError" и "ajaxComplete" – передаются дополнительные аргументы. Всем обработчикам этих событий будет передаваться два дополнительных аргумента. В первом дополнительном аргументе будет передаваться объект XMLHttpRequest, а во втором – объект с параметрами. Это означает, что обработчик события, например "ajaxSend", сможет добавлять собственные заголовки в объект XMLHttpRequest, подобно функции обратного вызова beforeSend. Обработчикам события "ajaxError" передается третий дополнительный аргумент помимо двух, только что описанных. В этом последнем аргументе будет передаваться объект Error, если таковой имеется, который был создан в результате возникшей ошибки. Довольно странно, но обработчикам событий архитектуры Ajax не передается код состояния, генерируемый библиотекой jQuery. Если, например, в обработчике события "ajaxSuccess" потребуется отличать состояния "success" и "notmodified", необходимо будет проверить код состояния HTTP-ответа в объекте XMLHttpRequest. Последние два события, перечисленные в таблице выше, отличаются от других тем, что не имеют соответствующих им функций обратного вызова, а также тем, что их обработчикам не передаются дополнительные аргументы. "ajaxStart" и "ajaxStop" – это пара событий, которые извещают о начале и окончании выполнения сетевых операций при выполнении Ajax-запроса. Когда библиотека jQuery не выполняет ни одного Ajax-запроса и инициируется новый запрос, она возбуждает событие "ajaxStart". Если до того, как завершится первый запрос, будут запущены новые запросы, эти новые запросы не будут вызывать появление нового события "ajaxStart". Событие "ajaxStop" генерируется, когда завершится последний Ajax-запрос и при этом библиотека jQuery уже не выполняет никаких сетевых операций. Эта пара событий может пригодиться для отображения и сокрытия анимированного сообщения «Загрузка...» или изображения, свидетельствующего о выполнении сетевых операций. Например:

$( "'"loading_animation'"). bind( {

ajaxStart: function() { $(this).show(); },

ajaxStop: function() { $(this).hide(); }

});

Обработчики событий "ajaxStart" и "ajaxStop" можно связать с любым элементом документа: библиотека jQuery генерирует их глобально (раздел 19.4.6), а не для какого-то конкретного элемента. Другие четыре события архитектуры Ajax- "ajaxSend", "ajaxSuccess", "ajaxError" и "ajaxComplete" – также обычно генерируются глобально, поэтому их обработчики также можно связать с любым элементом документа. Однако если установить параметр context при вызове функции jQuery.ajax(), эти четыре события будут генерироваться только в контексте указанного элемента.

Наконец, запомните, что появление всех событий архитектуры Ajax в библиотеке jQuery можно предотвратить, присвоив параметру global значение false. Несмотря на обескураживающее имя параметра global, присваивание ему значения false предотвращает возбуждение событий не только в глобальном масштабе, но и в объекте context.

содержание 19.7. Вспомогательные функции содержание

Библиотека jQuery определяет множество вспомогательных функций (и два свойства), которые могут вам пригодиться в ваших программах. Как вы увидите в списке ниже, для многих из этих функций теперь имеются эквиваленты в стандарте ECMAScript 5 (ES5). Функции в библиотеке jQuery были созданы еще до появления стандарта ES5 и действуют во всех браузерах. Ниже в алфавитном порядке перечислены вспомогательные функции:

jQuery.browser

Свойство browser является не функцией, а объектом, который можно использовать для определения типа браузера (раздел 13.4.5). Если сценарий выполняется в IE, свойство msie этого объекта будет иметь значение true. В Firefox и родственных ему браузерах значение true будет иметь свойство mozilla. В Safari и Chrome значение true будет иметь свойство webkit, а в браузере Opera значение true будет иметь свойство opera. В дополнение к этим свойствам объект browser имеет также свойство version, содержащее номер версии браузера. Приема определения типа браузера лучше стараться избегать, насколько это возможно, тем не менее это свойство можно использовать обхода ошибок, характерных для разных браузеров, как показано ниже:

if ($.browser.mozilla && parselnt($.browser.version) < 4) {

// Здесь обрабатывается гипотетическая ошибка в Firefox...

}

jQuery.contains()

Эта функция принимает в аргументах два элемента документа. Она возвращает true, если первый элемент содержит второй, иначе возвращает значение false.jQuery.each()

В отличие от метода each(), который выполняет итерации только по объектам jQuery, вспомогательная функция jQuery.each() способна выполнять итерации по элементам массива или свойствам объекта. В первом аргументе она принимает массив или объект, по которому выполняются итерации. Во втором аргументе принимается функция, которая должна быть вызвана для каждого элемента массива или свойства объекта. Этой функции передаются два аргумента: индекс элемента массива или имя свойства объекта и значение элемента массива или свойства объекта. Значение ссылки this в этой функции совпадает со значением второго аргумента. Если функция вернет false, jQuery.each() сразу же вернет управление, не завершив итерации. Функция jQuery.each() всегда возвращает значение первого аргумента.

Перечисление свойств функцией jQuery.each() выполняется в том же порядке, что и в обычном цикле for/in, т.е. в итерациях участвуют все перечислимые свойства, включая унаследованные. Перечисление элементов массива функцией jQuery.eachO выполняется в порядке следования их индексов, и она не пропускает неопределенные элементы в разреженных массивах.

jQuery.extend()

Эта функция принимает объекты в своих аргументах. Она копирует свойства из второго и всех последующих объектов в первый объект, затирая все одноименные свойства в первом объекте. Она пропускает все свойства, имеющие значение undefined или null. Если передать ей только один объект, свойства этого объекта будут скопированы в сам объект jQuery. Возвращаемым значением функции является объект, в который копировались свойства. Если в первом аргументе передать значение true, будет выполнено глубокое, или рекурсивное, копирование: второй аргумент будет дополнен свойствами третьего (и всех последующих) объектов.

Эту функцию удобно использовать для создания копий объектов и объединения объектов с параметрами с настройками по умолчанию: var clone = jQuery.extend({}, original);

var options = jQuery.extend({}, default_options, user_options); jQuery.globalEval()

Эта функция выполняет строку с программным кодом на языке JavaScript в глобальном контексте, как если бы она была содержимым элемента <script>. (В действительности эта функция создает элемент <script> и временно вставляет его в документ.)

jQuery.grep()

Эта функция похожа на метод filter() объекта Array, определяемый стандартом ES5. В первом аргументе она принимает массив, а во втором – функцию-предикат и вызывает эту функцию для каждого элемента массива, передавая ей значение и индекс элемента. Функция jQuery.grep() возвращает новый массив, содержащий только те элементы аргумента-массива, для которых функция-предикат вернула значение true (или другое значение, которое оценивается как истинное). Если в третьем аргументе передать функции jQuery. grep() значение true, она будет инвертировать возвращаемое значение функции-предиката и вернет массив элементов, для которых функция-предикат вернула ложное значение. jQuery.inArray()

Эта функция похожа на метод indexOf () объекта Array, определяемый стандартом ES5. В первом аргументе она принимает произвольное значение, а во втором – массив (или объект, подобный массиву) и возвращает индекс первого элемента в массиве, имеющего это значение, или –1, если указанное значение отсутствует в массиве.

jQuery.isArray()

Возвращает true, если аргумент является объектом Array.

jQuery.isEmptyObject()

Возвращает true, если аргумент не содержит перечислимых свойств. jQuery.isFunction()

Возвращает true, если аргумент является объектом Function. Обратите внимание, что в IE версии 8 и ниже такие методы, определяемые браузером, как Window.alert() и Element. attachEvent(), не являются функциями в этом смысле.

jQuery. isPlainObject()

Возвращает true, если аргумент является «простым» объектом, а не экземпляром некоторого более специализированного типа или класса объектов. jQuery.makeArray()

Если аргумент является объектом, подобным массиву, эта функция скопирует элементы из этого объекта в новый (истинный) массив и вернет этот массив. Если аргумент не является объектом, подобным массиву, эта функция просто вернет новый массив с аргументом в качестве единственного элемента. jQuery.map()

Эта функция похожа на метод тар() объекта Array, определяемый стандартом ES5. В первом аргументе она принимает массив или объект, подобный массиву, а во втором – функцию. Она передает указанной функции значение и индекс каждого элемента массива и возвращает новый массив, содержащий значения, возвращаемые функцией. jQuery.map() имеет пару отличий от метода тар() в стандарте ES5. Если ваша функция отображения вернет null, это значение не будет включено в массив с результатами. И если ваша функция отображения вернет массив, в результат будут добавлены элементы этого массива по отдельности, а не сам массив.

jQuery.mergeQ

Эта функция принимает два массива или объекта, подобных массивам, добавляет элементы второго массива в первый и возвращает первый массив. Первый массив изменяется, а второй – нет. Обратите внимание, что эту функцию можно использовать для поверхностного копирования массивов, как показано ниже: var clone = jQuery.merge([], original);

jQuery. parseJSON()

Эта функция разбирает строку в формате JSON и возвращает результат. Она возбуждает исключение, если в исходной строке будет обнаружена ошибка. Библиотека jQuery использует стандартную версию функции JSON.parse(), если она определена в браузере. Обратите внимание, что в библиотеке jQuery имеется только функция разбора строк в формате JSON, но в ней отсутствует функция сериализации объектов в формат JSON.

jQuery.proxy()

Эта функция напоминает метод bind() (раздел 8.7.4) объекта Function, определяемый стандартом ES5. В первом аргументе она принимает функцию, а во втором – объект и возвращает новую функцию, которая вызывает оригинальную как метод указанного объекта. Она не выполняет частичное применение аргументов, как метод bind().

Функция jQuery.proxy() может также вызываться с объектом в первом аргументе и именем свойства во втором. Значение свойства с указанным именем должно быть функцией. В этом случае вызов функции jQuery. proxy(o.n) вернет то же, что и вызов jQuery.proxy(o[n],o).

Функция jQuery.proxy() предназначена для использования с механизмом связывания обработчиков событий в библиотеке jQuery. Если в качестве обработчика была связана функция, полученная с помощью jQuery. proxy(), то удалить ее можно, указав ее оригинал.

jQuery.support

Это свойство подобно свойству jQuery.browser, но оно предназначено для переносимой проверки поддерживаемых возможностей (раздел 13.4.3) вместо isfe- нее надежного способа определения типа браузера. Значением свойства jQuery. support является объект, все свойства которого имеют логические значения и определяют наличие или отсутствие поддержки различных возможностей браузеров. Большинство свойств объекта jQuery.support содержат низкоуровневую информацию, используемую внутренними механизмами библиотеки jQuery. В основном они представляют интерес для разработчиков расширений и мало чем полезны прикладным программистам. Одно исключение – свойство jQuery.support.boxModel: оно имеет значение true, если браузер использует блочную модель "context-box", соответствующую стандарту CSS, и значение false в IE6 и IE7, работающих в режиме совместимости (раздел 16.2.3.1). jQuery.trim()

Эта функция похожа на метод trim(), добавленный в строки стандартом ES5. Она принимает единственный строковый аргумент и возвращает его копию, из которой удалены начальные и завершающие пробельные символы.

содержание 19.8. Селекторы и методы выбора в библиотеке jQuery содержание

На протяжении всей главы мы использовали функцию выбора $() из библиотеки jQuery, применяя простые CSS-селекторы. Теперь пришло время поближе познакомиться с грамматикой селекторов jQuery, а также с некоторыми методами, позволяющими фильтровать и расширять множество выбранных элементов.

содержание 19.8.1. Селекторы jQuery

Библиотека jQuery поддерживает достаточно полное подмножество селекторов, определяемых проектом стандарта "CSS3 Selectors", расширенное нестандартными, но очень удобными псевдоклассами. Основы CSS-селекторов обсуждались в разделе 15.2.5. Здесь мы продолжим это обсуждение и дополнительно познакомимся с более сложными селекторами. Имейте в виду, что в этом разделе описываются селекторы, реализованные в библиотеке jQuery. Многие из них могут использоваться в таблицах стилей CSS, но не все.

Грамматика селекторов делится на три уровня. Вы наверняка уже встречались с простейшими видами селекторов ранее. Селектор "#test" выбирает элемент с атрибутом id, имеющим значение "test". Селектор "blockquote" выбирает все элементы <blockquote> в документе, а селектор "div.note" выбирает все элементы <div> с атрибутом class, имеющим значение "note". Простые селекторы можно объединять в «комбинированные селекторы», такие как "div.note>p" и "blockquote i", отделяя их символом-комбинатором. И простые, и комбинированные селекторы можно группировать в списки, отделяя их точкой с запятой. Такие группы селекторов являются наиболее универсальной разновидностью селекторов, обычно передаваемых функции $(). Прежде чем перейти к обсуждению комбинированных селекторов и групп селекторов, необходимо познакомиться с синтаксисом простых селекторов.

содержание 19.8.1.1. Простые селекторы

Простой селектор начинается (явно или неявно) с имени тега. Если, к примеруг интерес представляют только элементы <р>, простой селектор должен начинаться с *р». Если требуется выбрать элементы независимо от имени тега, используется шаблонный символ "*". Если селектор не начинается с имени тега или шаблонного символа, подразумевается присутствие шаблонного символа. Имя тега или шаблонный символ определяют начальное множество элементов документа, кандидатов на выбор. Фрагмент селектора, следующий за определением имени тега, состоит из нуля или более фильтров. Фильтры применяются слева направо, в порядке их следования, и каждый из них сужает множество выбранных элементов. Фильтры, поддерживаемые библиотекой jQuery, см. в табл. 19.1. Обратите внимание, что некоторые из фильтров, перечисленных в табл. 19.1, принимают аргументы в круглых скобках. Следующий селектор, например, выберет абзацы, которые являются первыми или каждыми третьими дочерними элементами своих родителей при условии, что они содержат слово "JavaScript" и не содержат элемент <а>.

p:nth-child(3n+1):text(JavaScript):not(:has(a))

Обычно фильтры действуют более эффективно, если им предшествует имя тега. Например, вместо использования простого фильтра ":radio" для выбора радиокнопок лучше использовать селектор "input:radio". Исключение составляют фильтры, проверяющие значение атрибута id, которые наиболее эффективно действуют, когда они употребляются автономно. Например, селектор "#address" обычно действует эффективнее, чем более явный селектор *form#address". Таблица 19.1. Фильтры селекторов, поддерживаемые библиотекой jQuery Фильтр

Описание

Hid

.class

[attr]

[attr=val]

[attr\=val]

[attr=val]

[attr$=val]

[attr*=val]

[attr'=val]

Соответствует элементам с атрибутом id, имеющим значение id. Допустимые HTML-документы никогда не имеют более одного элемента с одним и тем же значением в атрибуте id, поэтому этот фильтр обычно используется как самостоятельный селектор.

Соответствует элементам с атрибутом class, значение которого (интерпретируется как список слов, разделенных пробелами) включает слово class. Соответствует элементам, имеющим атрибут attr (независимо от значения). Соответствует элементам, имеющим атрибут attr со значением val. Соответствует элементам, не имеющим атрибут attr, или элементам с атрибутом attr9 значение которого не равно val (расширение jQuery). Соответствует элементам с атрибутом attr, значение которого начинается с val.

Соответствует элементам с атрибутом attr, значение которого оканчивается на val.

Соответствует элементам с атрибутом attr, значение которого содержит val. Соответствует элементам с атрибутом attr, когда элемент,

интерпретируемый как список слов, разделенных пробелами, содержит слово val. To есть селектор "div.note" – это то же самое, что и "div[class~=note]".

Фильтр

Описание

[attr\=val]

:animated

:button

xheckbox

:checked

xontains(text)

:disabled

:empty

:enabled

:eq(n)

:file

:first

:first-child

:gt(n)

:has(seJ)

:header

:hidden

: image

:input

Соответствует элементам с атрибутом attr, значение которого начинается с val и, возможно, следующим за ним дефисом и любыми другими символами.

Соответствует элементам, к которым в настоящее время применяется анимационный эффект jQuery.

Соответствует элементам <script> <button type="button"> и <script> <input type="'button"> (расширение jQuery).

Соответствует элементам <script> <input type=* checkbox > (расширение jQuery). Эффективнее всего использовать этот фильтр с именем тега input: "in- put:checkbox".

Соответствует отмеченным элементам ввода.

Соответствует элементам, содержащим указанный текст text (расширение jQuery). Текст в этом фильтре ограничивают круглые скобки, т. е. кавычки здесь не нужны. Текстовое содержимое элементов проверяется этим фильтром по значениям их свойств textContent и innerText; это простой, необработанный текст документа, из которого исключены теги и комментарии.

Соответствует элементам в запрещенном состоянии.

Соответствует элементам, не имеющим потомков, в том числе текстовых узлов.

Соответствует элементам в незапрещенном состоянии.

Соответствует только л-му элементу в списке совпадений, расположенных в порядке следования в документе, отсчет в котором начинается с нуля (расширение jQuery).

Соответствует элементам с четными индексами в списке. Поскольку первый элемент имеет индекс 0, фактически этот фильтр соответствует первому, третьему, пятому (и так далее) элементам (расширение jQuery). Соответствует элементам <script> <input type="file"> (расширение jQuery). Соответствует только первому элементу в списке. То же, что и :eq(0) (расширение jQuery).

Соответствует только элементам, которые являются первыми дочерними элементами своих родителей. Обратите внимание, что этот фильтр полностью отличается от фильтра :first.

Соответствует элементам в списке совпадений, расположенным в порядке следования в документе, отсчет в котором начинается с нуля, чей индекс больше значения п (расширение jQuery).

Соответствует элементам, имеющим потомков, соответствующих

селектору seJ.

Соответствует любым элементам-заголовкам: <h1>, <h2>, <h3>, <h4>, <h5> или <h6> (расширение jQuery).

Соответствует всем невидимым на экране элементам, т. е. элементам, значения свойств offsetWidth и offsetHeight которых равны 0. Соответствует элементам <input type="image">. Обратите внимание, что этот фильтр не соответствует элементам <img> (расширение jQuery). Соответствует элементам ввода: <input>, <textarea>, <select> и <button> (расширение jQuery).

Таблица 19.1 (продолжение)

Описание

Соответствует последнему элементу в списке совпадений (расширение jQuery).

Соответствует всем элементам, которые являются последними дочерними элементами своих родителей. Обратите внимание, что этот фильтр полностью отличается от фильтра :last.

Соответствует элементам в списке совпадений, расположенным в порядке следования в документе, отсчет в котором начинается с нуля, чей индекс меньше значения п (расширение jQuery).

Соответствует элементам, которые не соответствуют селектору sel. Синоним фильтра :eq(n) (расширение jQuery).

Соответствует элементам, которые являются n-ми дочерними элементами своих родителей, n может быть числом, словом "even", словом "odd" или формулой. Для выбора второго, четвертого (и так далее) элементов в списках дочерних элементов их родителей можно использовать фильтр :nth-child(even). Для выбора первого, третьего (и так далее) элементов можно использовать фильтр :nth-child (odd).

В самом общем случае n может быть формулой вида xn или xn+y, где x и y являются целыми числами, а n – символом n. То есть фильтр nth-child(3n+1) выберет первый, четвертый, седьмой (и так далее) элементы.

Обратите внимание, что отсчет индексов в этом фильтре ведется с единицы, поэтому индекс первого дочернего элемента его родителя считается нечетным и он соответствует формуле Зn+1, но не соответствует формуле Зn. Сравните этот фильтр с фильтрами :even и :odd, которые начинают отсчет элементов в списке совпадений с нуля.

Соответствует элементам с нечетными индексами в списке (отсчет начинается с нуля). Обратите внимание, что элементы с индексами 1 и 3 являются вторым и четвертым элементами, соответственно (расширение jQuery). Соответствует элементам, являющимся единственными дочерними элементами своих родителей.

Соответствует элементам, которые являются родителями. Этот фильтр является обратным по отношению к фильтру :empty (расширение jQuery). Соответствует элементам <input type="password"> (расширение jQuery). Соответствует элементам <input type="radio"> (расширение jQuery). Соответствует элементам <input type="reset"> и <button type="reset"> (расширение jQuery).

Соответствует элементам <option>, которые были отмечены. Для выбора отмеченных флажков и переключателей (радиокнопок) используйте фильтр xhecked (расширение jQuery).

Соответствует элементам <input type="submit'"> и <button type='submit"> (расширение jQuery).

Соответствует элементам <input type=" text"> (расширение jQuery). Соответствует всем элементам, которые видимы в текущий момент, т. е. элементам, свойства offsetWidth и offsetHeight которых не равны нулю. Этот фильтр является обратным по отношению к фильтру : hidden.

содержание 19.8.1.2. Комбинированные селекторы

Простые селекторы могут объединяться с использованием специальных операторов, или «комбинаторов», для представления отношений между элементами в дереве документа. В табл. 19.2 перечислены комбинированные селекторы, поддерживаемые библиотекой jQuery. Эти же комбинированные селекторы поддерживаются стандартом CSS3.

Ниже приводится несколько примеров комбинированных селекторов: "blockquote i" // Соответствует элементу <i> в элементе <blockquote> "ol > И" // Элемент <П>, прямой потомок элемента <ol>

" floutput + *" // Братские элементы, следующие за элементом с id="outpuf "div.note > hi + р" // Элемент <р>, следующий за <h1> в <div class="note"> Обратите внимание, что комбинированные селекторы не ограничены комбинациями из двух селекторов: допустимыми являются также комбинации из трех и более селекторов. Обработка комбинированных селекторов выполняется слева направо. Таблица 19.2. Комбинированные селекторы, поддерживаемые библиотекой jQuery Комбинирован- | Описание

ный селектор

А В

А > В

А + В

А ~ В

Выбирает элементы документа, которые соответствуют селектору В и являются потомками элементов, соответствующих селектору А. Обратите внимание, что здесь символом-комбинатором является простой пробел. Выбирает элементы документа, которые соответствуют селектору В и являются непосредственными потомками элементов,

соответствующих селектору А.

Выбирает элементы документа, которые соответствуют селектору В и следуют непосредственно за элементами, соответствующими

селектору А (текстовые узлы и комментарии в учет не принимаются). Выбирает элементы документа, которые соответствуют селектору В и являются братскими для элементов, соответствующих селектору А.

содержание 19.8.1.3. Группы селекторов

Группа селекторов, которая является разновидностью селекторов, передаваемых функции $() (или используемых в таблицах стилей), – это просто список простых или комбинированных селекторов, разделенных запятыми. Группе селекторов соответствуют все элементы, которые соответствуют любому из комбинированных селекторов в группе. С позиции нашего обсуждения даже простой селектор можно рассматривать как комбинированный. Ниже приводится несколько примеров групп селекторов:

" hi, h2, h3" // Соответствует элементам <h1>, <h2> и <h3>

" #р1, #р2, flp3" // Соответствует элементам с id, равным р1, р2 и рЗ "div.note, p.note" // Соответствует элементам <div> и <р> с class="note" "body>p,div.note>p" // <р>, вложенный в <body>, и <div class="note"> Обратите внимание, что синтаксис селекторов CSS и jQuery позволяет использовать круглые скобки в некоторых фильтрах в простых селекторах, но не допускает более обобщенного их использования для группировки селекторов. Нельзя поместить группу селекторов или комбинированный селектор в скобки и интерпретировать их как простой селектор, например:

(hi, h2, h3)+p // Недопустимо

h1+p, h2+p, h3+p // Следует использовать этот вариант

содержание 19.8.2. Методы выбора

В дополнение к грамматике селекторов, поддерживаемой функцией $(), библиотека jQuery определяет несколько методов выбора. Большинство методов из библиотеки jQuery, с которыми мы встречались в этой главе до сих пор, выполняют некоторые операции над выбранными элементами. Методы выбора отличаются от них: они изменяют множество выбранных элементов, фильтруя, расширяя или используя его в качестве отправной точки для нового выбора. В данном разделе описываются эти методы выбора. Здесь вы увидите, что многие методы реализуют те же функциональные возможности, которые обеспечивает грамматика селекторов.

Самой простой является операция фильтрации выбора по позициям элементов в выбранном множестве. Метод first() возвращает объект jQuery, содержащий только первый выбранный элемент, а метод last() возвращает объект jQuery, содержащий только последний выбранный элемент. Более обобщенный метод eq() возвращает объект jQuery, содержащий единственный выбранный элемент с указанным индексом. (В версии jQuery 1.4 допускается использовать отрицательные индексы, в этом случае отсчет начинается с конца выбранного множества.) Обратите внимание, что эти методы возвращают объект jQuery с единственным элементом, что отличает их от обычной операции индексирования массива, которая возвращает единственный элемент без объекта jQuery, обертывающего его: var paras = $("р");

paras.first() // Выберет только первый элемент <р>

paras.last() // Выберет только последний элемент <р>

paras.eq(1) // Выберет второй элемент <р>

paras.eq(-2) // Выберет второй с конца элемент <р>

paras[1] // Сам второй элемент <р>

Универсальным методом фильтрации выбора по позиции является метод slice(). Этот метод действует подобно методу Array. slice(): он принимает начальный и конечный индексы (отрицательные индексы откладываются от конца массива) и возвращает объект jQuery, содержащий элементы с индексами от начального до конечного, не включая его. Если конечный индекс не указан, возвращаемый объект будет содержать все элементы от начального индекса и до конца: $("p").slice(2,5) // Выберет 3-й, 4-й и 5-й элементы <р>

$("div").slice(-3) // Последние три элемента <div>

Метод filter() является универсальным методом фильтрации и может использоваться тремя разными способами:

• Если передать методу f ilter() строку с селектором, он вернет объект jQuery, содержащий только те из выбранных элементов, которые соответствуют этому селектору.

• Если передать методу filter() другой объект jQuery, он вернет новый объект jQuery, содержащий пересечение множеств элементов в двух исходных объектах jQuery. Методу можно также передать массив элементов и даже единственный элемент документа.

• Если передать методу f ilter() функцию-предикат, эта функция будет вызвана для каждого выбранного элемента и метод f ilter() вернет объект jQuery, содержащий только те элементы, для которых функция-предикат вернет true (или любое другое истинное значение). Элемент будет передан функции в виде значения ссылки this, а индекс элемента – в виде аргумента. (Смотрите также описание метода jQuery.grep() в разделе 19.7.)

$("div").filter(".note") // Аналогично $("div.note")

$C'div"').filter($(".note")) // Аналогично $("'div.note")

$(""div"). filter(function(idx) { return idx%2==0 }) // Аналогично $C'div:everr) Метод not() действует точно так же, как метод filter(), за исключением того, что он инвертирует значение фильтра. Если передать методу not() строку с селектором, он вернет новый объект jQuery, содержащий только те из выбранных элементов, которые не соответствуют селектору. Если передать методу not() объект jQuery, массив элементов или единственный элемент, он вернет все выбранные элементы, кроме тех, что были явно указаны. Если передать методу not() функцию- предикат, он вызовет ее для каждого выбранного элемента, как и метод filter(), но вернет объект jQuery, содержащий только те выбранные элементы, для которых функция возвратит false или любое другое ложное значение: $("div").not(""header, "footer"); // Все элементы <div>, кроме двух указанных В версии jQuery 1.4 имеется метод has(), обеспечивающий еще один способ фильтрации выбора. Если ему передать селектор, он вернет новый объект jQuery, содержащий только те из выбранных элементов, которые имеют потомков, соответствующих селектору. Если передать методу has() элемент документа, он вернет только те выбранные элементы, которые являются предками указанного элемента: $('p").has("a[href]") // Абзацы, включающие ссылки

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

// Эквивалентные способы выбора всех элементов <div> и <р>

$("div, p") // Используется группа селекторов

$("div").add("p") // Передать методу add() селектор

$("div').add($("p')) // Передать методу add() объект jQuery

var paras = document.getElementsByTagName("p"); // Объект, подобный массиву $("div").add(paras); // Передать методу add() массив элементов

содержание 19.8.2.1. Использование результатов выбора в качестве контекста

Методы filter(), add() и not(), описанные выше, возвращают пересечение, объединение и разность независимых множеств выбранных элементов. Библиотека jQuery определяет также несколько других методов выбора, которые используют текущее множество выбранных элементов в качестве контекста. Для каждого выбранного элемента эти методы создают новое множество, используя выбранный элемент в качестве контекста, или отправной точки, и возвращают новый объект jQuery, содержащий объединение этих множеств. Как и метод add(), эти методы удаляют повторные вхождения одних и тех же элементов и сортируют их в порядке следования в документе.

Наиболее универсальным в этой категории методов выбора является метод f ind(). Он выполняет поиск потомков в каждом выбранном элементе, соответствующих указанной строке селектора, и возвращает новый объект jQuery, представляющий новое множество соответствующих потомков. Обратите внимание, что вновь выбранные элементы не объединяются с существующим множеством – они возвращаются в виде нового множества элементов. Отметьте также, что метод f ind() отличается от метода filter(), который просто сужает текущее множество выбранных элементов, не добавляя новых:

$("div").find("p") // Отыскать элементы <р> в <div>. To же, что и $("div р") Другие методы из этой категории возвращают новые объекты jQuery, представляющие дочерние, братские или родительские элементы для каждого выбранного элемента. Чаще всего им передается необязательный строковый аргумент с селектором. При вызове без селектора они возвращают, соответственно, все дочерние, братские или родительские элементы. При вызове с селектором они фильтруют список и возвращают только элементы, соответствующие селектору. Метод children() возвращает дочерние элементы каждого выбранного элемента, фильтруя результат с применением необязательного селектора:

// Отыскать все элементы , которые являются дочерними для элементов // с id="header" и id="footer". Тот же результат дает вызов

// $("#header>span,#footer>span')

$(""header, "footer").children("span")

Метод contents() действует так же, как метод children(), но возвращает все дочерние узлы, включая текстовые, каждого выбранного элемента. Кроме того, для элементов метод contentsQ возвращает объект Document с содержимым этого элемента. Обратите внимание, что метод contentsQ не принимает необязательный строковый аргумент с селектором – это обусловлено тем, что он возвращает объекты Document, не являющиеся элементами, а селекторы позволяют описывать только элементы.

Методы next() и prev() возвращают следующий и предыдущий братский элемент для каждого выбранного элемента, если они имеются. Если методу передать селектор, выбраны будут только братские узлы, соответствующие селектору: $("h1").next("p") // То же, что и $("п1+р")

$("h1").prev() // Братские элементы перед элементами <h1>

Методы nextAH() и prevAH() возвращают все следующие и предыдущие братские элементы (если имеются) для каждого выбранного элемента. А метод siblingsQ возвращает все братские элементы для каждого выбранного элемента (элементы не считаются братскими по отношению к самим себе). Если любому из этих методов передать селектор, выбраны будут только братские узлы, соответствующие селектору:

$("#footer").nextAll("p") // Все братские элементы <р>. следующие за "footer $C#footer").prevAll() // Все братские элементы, предшествующие "footer В версии jQuery 1.4 и выше методы nextUntilO и prevllntilQ принимают аргумент с селектором и выбирают все братские элементы, следующие за выбранным элементом или предшествующие ему, пока не будет встречен братский элемент, соответствующий селектору. При вызове без селектора они действуют точно так же, как методы nextAll() и prevAH() при вызове их без селектора.

Метод parent() возвращает родителя для каждого выбранного элемента: $("И").parent() // Родители элементов списка, такие как <ul> и <ol> Метод parents() возвращает предков (вплоть до элемента <html>) для каждого выбранного элемента. Оба метода, parent() и parents(), принимают необязательный строковый аргумент с селектором:

$("a[href]").parents("p") // Элементы <р>, содержащие ссылки

Метод parentsllntilO выбирает предков для каждого выбранного элемента, пока не будет встречен первый предок, соответствующий указанному селектору. Метод closestO принимает обязательный строковый аргумент с селектором и возвращает ближайшего предка (если имеется) для каждого выбранного элемента, соответствующего селектору. Этот метод рассматривает элементы как предки самим себе. В версии jQuery 1.4 методу closestO можно также передать второй необязательный аргумент, чтобы не дать библиотеке jQuery подняться по дереву предков выше указанного в этом аргументе элемента:

$("a[href]").closest('div") // Самые внутренние элементы <div>, содержащие ссылки $("a[href]").parentsUntil(":not(div)") // Все элементы <div>, непосредственно // обертывающие элементы <а>

содержание 19.8.2.2. Возврат к предыдущему выбору

Чтобы обеспечить возможность составления цепочек вызовов методов, большинство методов объекта jQuery возвращают объект, относительно которого они вызываются. Однако все методы, которые рассматривались в этом разделе, возвращают новые объекты jQuery. Они также могут включаться в цепочку вызовов, но вы должны иметь в виду, что методы, вызываемые в цепочке вслед за ними, будут оперировать другим множеством элементов, отличным от того, которое использовалось в начале цепочки.

Однако на самом деле ситуация несколько сложнее. Когда методы выбора, описанные здесь, создают и возвращают новый объект jQuery, они сохраняют в нем ссылку на прежний объект jQuery, на основе которого был порожден новый объект. В результате создается список, или стек объектов jQuery. Метод end() выталкивает объект на вершине этого стека и возвращает сохраненный объект jQuery. Вызов метода end() в цепочке восстанавливает множество выбранных элементов в предыдущее состояние. Взгляните на следующий фрагмент:

// Отыскать все элементы <div>, затем внутри множества выбранных элементов отыскать // элементы <р>. Выделить элементы <р> цветом и затем окружить рамками элементы <div>. // Сначала рассмотрим, как это сделать без цепочек вызовов методов var divs = $C"div");

var paras = divs. findC"p");

paras.addClass("highlight");

divs.css( "border", "solid black 1px");

// А теперь то же самое, составив цепочку вызовов методов

$('"div").find("p'").addClass("highlight").end().css("border", "solid black 1px"); // To же самое можно реализовать без вызова метода end(). просто переупорядочив операции $("div").css( "border", "solid black 1px").find('p").addClass( "highlight"); Если вам когда-нибудь потребуется вручную определить множество выбранных элементов и обеспечить его совместимость с методом end(), передайте новое множество элементов в виде массива или в виде объекта, подобного массиву, методу pushStack(). Указанные элементы будут преобразованы в новое множество выбранных элементов, а предыдущее множество будет помещено в стек, откуда его можно будет извлечь вызовом метода end():

var sel = $("div"); // Выбрать все <div>

sel.pushStack(document.getElementsByTagName('p'")); // Заменить его множеством // всех элементов <р>

sel.end(); // Восстановить множество элементов <div>

Теперь, когда мы познакомились с методом end() и со стеком, хранящим множества выбранных элементов, нам осталось познакомиться с еще одним методом. Метод andSelf() возвращает новый объект jQuery, включающий все элементы из текущего множества выбранных элементов плюс все элементы (за исключением дубликатов) из предыдущего множества. Метод andSelf () действует подобно методу add() и для него больше подошло бы имя "addPrev". В качестве примера рассмотрим следующий вариант реализации предыдущего примера: он выделяет цветом элементы <р> и вмещающие их элементы <div> и затем добавляет рамки к элементам <div>:

$("div").find("p").andSelf(). // Отыскать <р> в <div> и объединить их addClass("highlight"). // Выделить их все цветом

end().end(). // Вытолкнуть со стека дважды до $( "div")

содержание 19.9. Расширение библиотеки jQuery содержание

с помощью модулей расширений

Библиотека jQuery написана так, что позволяет легко добавлять в нее новые функциональные возможности. Модули, добавляющие новые функциональные возможности, называются расширениями (plug-in), большое количество которых можно отыскать на сайте http://plugins.jquery.com. Расширения для библиотеки jQuery являются обычными файлами с программным кодом на языке JavaScript, и, чтобы задействовать их в своих веб-страницах, достаточно просто подключить их с помощью элемента <script>, как любую другую библиотеку на языке JavaScript (разумеется, расширения должны подключаться после подключения самой библиотеки jQuery).

Создание собственных расширений для библиотеки jQuery является почти тривиальной задачей. Вся хитрость заключается в объекте-прототипе jQuery.f n, который является прототипом для всех объектов jQuery. Если добавить новую функцию в этот объект, она превратится в метод объекта jQuery. Например:

jQuery.fn.println = function() {

// Объединить все аргументы в одну строку, разделив их пробелами var msg = Array.prototype.join.call(arguments, " ");

// Обойти в цикле все элементы в объекте jQuery

this.each(function() {

// В конец каждого из них добавить строку с простым текстом и <br/>. jQuery(this).append(document.createTextNode(msg)).append( '"<br/>"); }):

// Вернуть объект jQuery, чтобы обеспечить возможность составления цепочек return this;

};

Определив эту функцию jQuery.fn.println, мы получаем возможность вызывать метод println() относительно любого объекта jQuery, как показано ниже: $( ""debug").println("x = ", х, "; у = ", у);

В jQuery.fn постоянно добавляются новые методы. Если обнаружится, что приходится «вручную» выполнять обход элементов в объекте jQuery с помощью метода each() и выполнять над ними некоторые операции, – это повод задуматься о необходимости реструктуризации программного кода, чтобы переместить вызов метода each() в дополнительный метод. Если при создании такого метода следовать приемам модульного программирования и соблюдать некоторые соглашения, принятые в библиотеке jQuery, этот дополнительный метод можно назвать расширением и поделиться им с другими. Ниже приводится перечень соглашений, которым необходимо следовать при создании расширений для библиотеки jQuery: • Не полагайтесь на идентификатор $: подключающая страница может вызывать функцию jQuery. noConf lict(), после чего $() уже не будет синонимом функции jQuery(). В коротких расширениях, как в примере выше, можно просто использовать имя jQuery вместо $. Если вы создаете большое расширение, то вы наверняка обернете его единственной анонимной функцией, чтобы избежать создания глобальных переменных. В этом случае можно использовать распространенный прием передачи ссылки на функцию jQuery в виде аргумента и принимать это значение в параметре с именем $:

(function($) { // Анонимная функция с одним параметром $

// Здесь находится реализация расширения

}(jQuery)); // Вызвать функцию с объектом jQuery в виде аргумента • Если метод расширения не должен возвращать какое-то свое значение, он должен возвращать объект jQuery, чтобы этот метод можно было использовать в цепочках вызовов. Обычно этот объект передается методам в виде ссылки this, которую можно просто вернуть вызывающей программе. Метод в примере выше завершается строкой return this;. Некоторые методы можно немного сократить (и сделать их сложнее для понимания), используя еще один распространенный прием: возвращая результат метода eachQ. Например, метод println() мог бы содержать программный код return this.each(function() {...}); • Если метод расширения принимает более двух параметров или параметров настройки, дайте пользователю метода передавать параметры в форме объекта (как мы видели на примере метода animate() в разделе 19.5.2 и функции jQuery.ajax() в разделе 19.6.3).

• Не засоряйте пространство имен jQuery лишними методами. Правильно оформленные расширения для библиотеки jQuery определяют минимальное количество методов, образуя непротиворечивый и удобный прикладной интерфейс. Обычно расширения jQuery определяют в объекте jQuery.f n единственный метод. Этот метод принимает в первом аргументе строку и интерпретирует ее как имя функции, которой следует передать остальные аргументы. Если расширение определяет единственный метод, его имя должно совпадать с именем расширения. Если необходимо определить более одного метода, в именах методов следует использовать имя расширения в качестве префикса.

• Если расширение привязывает обработчики событий, их следует поместить в пространство имен событий (раздел 19.4.4). В качестве имени пространства имен следует использовать имя расширения.

• Если расширение использует метод data() для связывания данных с элементами, все данные следует помещать в единственный объект и хранить его как единственное значение, дав ему имя, совпадающее с именем расширения. • Файл с программным кодом расширения должен иметь имя в формате "jQuery, plugin.js", где подстроку "plugin" следует заменить на имя расширения. Расширения могут определять новые вспомогательные функции, добавляя их в сам объект jQuery. Например:

// Этот метод выводит свои аргументы (с помощью метода расширения printlnO) // в элемент с атрибутом id="debug". Если такой элемент отсутствует, он будет // создан и добавлен в документ.

jQuery.debug = function() {

var elt = jQueryC'fldebug'); // Отыскать элемент "debug

if (elt.length == 0) { // Создать, если он отсутствует

elt = jQuery('

}

elt.println.apply(elt. arguments); // Вывести в него аргументы };

Помимо создания новых методов можно также расширять и другие части библиотеки jQuery. В разделе 19.5, например, мы узнали, что имеется возможность добавлять новые имена, определяющие продолжительность визуальных эффектов (вдобавок к "fast" и "slow"), создавая новые свойства в объекте jQuery.fx.speeds, и добавлять новые функции переходов, включая их в объект jQuery.easing. Более того, с помощью расширений можно даже добавлять новые возможности в механизм селекторов библиотеки jQuery! Например, можно определить новые псевдоклассы фильтров (такие как :first и :input), добавив свойства в объект jQuery. expr[':]. Ниже приводится пример определения нового фильтра : draggable, который возвращает только элементы с атрибутом draggable=true: jQuery.expr[':'].draggable = function(e) { return e.draggable === true; }; Добавив этот фильтр, мы сможем выбирать доступные для буксировки изображения вызовом $("img:draggable") вместо более длинного $("img[draggable=true]"). Как можно заметить в примере выше, функции фильтра передается элемент DOM – кандидат на выбор. Она должна вернуть true, если элемент соответствует фильтру, и false – в противном случае. Многие нестандартным фильтрам достаточно одного аргумента с элементом, но в действительности им передается четыре аргумента. Во втором аргументе передается целочисленный индекс, определяющий позицию элемента в массиве кандидатов. Этот массив передается в четвертом аргументе, но ваша функция фильтра не должна модифицировать его. В третьем аргументе передается весьма интересное значение: это массив результатов вызова метода.ехес() объекта RegExp. В четвертом элементе этого массива (с индексом 3) хранится значение, переданное псевдоклассу фильтра в круглых скобках (если оно имеется). Из этого значения удаляются все скобки и кавычки, и остается только строка. Например, ниже показано, как можно было бы реализовать псевдокласс :data(x), возвращающий true только для элементов, имеющих атрибут data-x (раздел 15.4.3):

jQuery.expr[':'].data = function(element, index, match, array) { // Примечание: В IE версии 7 и ниже метод hasAttribute() отсутствует return element.hasAttribute("data-" + match[3]);

}:

содержание 19.10. Библиотека jQuery Ul содержание

Функциональные возможности, поддерживаемые библиотекой jQuery, сосредоточены на методах для работы с деревом DOM, стилями CSS, обработчиками событий и поддержки архитектуры Ajax. Все вместе это является отличным фундаментом для построения высокоуровневых абстракций, таких как виджеты пользовательского интерфейса, которые предоставляет библиотека jQuery UL Полный охват возможностей библиотеки jQuery UI выходит далеко за рамки этой книги, и все, что нам доступно, – это краткий обзор. Саму библиотеку и документацию к ней можно найти на сайте http://jqueryui.com.

Как следует из ее имени, библиотека jQuery UI определяет множество виджетов пользовательского интерфейса: поля ввода с функцией автодополнения, элементы выбора даты, многостраничные виджеты и вкладки для организации информации, движки и индикаторы хода выполнения операции для визуального представления числовых значений и модальные диалоги для срочного оповещения пользователя. В дополнение к этим виджетам библиотека jQuery UI реализует более универсальные «механизмы взаимодействий», позволяющие легко сделать любой элемент документа буксируемым, изменяющим размеры, выбираемым или сортируемым. Наконец, библиотека jQuery UI определяет множество новых методов визуальных эффектов (включая возможность изменять цвет) вдобавок к тем, что предлагаются самой библиотекой jQuery, и добавляет множество новых функций переходов.

Библиотеку jQuery UI можно представить как пакет расширений для библиотеки jQuery, помещенных в один файл. Чтобы воспользоваться библиотекой jQuery UI, достаточно просто подключить ее к веб-странице после подключения основной библиотеки jQuery. На странице Download (Загрузка), на сайте http://jqueryui.com, можно выбрать компоненты, которые предполагается использовать, и сконструировать собственную версию библиотеки, что поможет вам сократить время загрузки ваших страниц в сравнении со случаем использования полной версии библиотеки jQuery UL

Библиотека jQuery UI поддерживает темы оформления, которые реализуются в виде файлов CSS. То есть помимо загрузки в ваши страницы программного кода библиотеки jQuery UI вам также придется подключить файл CSS с выбранной темой оформления. На сайте библиотеки jQuery UI имеется множество готовых тем оформления, а также страница "ThemeRoller", позволяющая настраивать и загру; жать собственные темы оформления.

Виджеты и механизмы взаимодействий в библиотеке jQuery UI оформлены в виде расширений, каждое из которых определяет единственный метод объекта jQuery. Обычно, когда такие методы применяются к существующим элементам документа, они преобразуют эти элементы в виджеты. Например, чтобы превратить текстовое поле ввода в виджет выбора даты, при щелчке на котором отображается календарик, достаточно просто вызвать метод datepickerQ, как показано ниже: // Превратить элементы <input> с атрибутом class="date" в виджеты выбора даты $( "input.date").datepicker();

Для полноценного использования виджета из библиотеки jQuery UI необходимо знать три вещи: его параметры настройки, его методы и его события. Все виджеты в библиотеке jQuery UI являются настраиваемыми, и некоторые из них имеют весьма значительное количество настроек. Поведение и внешний вид виджетов можно настраивать, передавая объект с параметрами (подобный объекту с параметрами, который передается методу animateO) методу виджета. Виджеты в библиотеке jQuery UI обычно определяют хотя бы несколько * методов» взаимодействия с виджетом. Однако, чтобы избежать быстрого роста количества методов объекта jQuery, виджеты в библиотеке jQuery UI определяют свои «методы» не как настоящие методы. Каждый виджет имеет всего один метод (такой как метод datepicker() в примере выше). Когда необходимо вызвать «метод» виджета, имя требуемого «метода» передается единственному настоящему методу, определяемому виджетом. Например, чтобы перевести виджет выбора даты в состояние запрещения, не нужно вызывать его метод disableDatepicker(); вместо этого нужно вызвать datepicker("disable").

Как правило, виджеты в библиотеке jQuery UI определяют собственные события, которые генерируются в ответ на действия пользователя. Установить обработчики этих событий можно с помощью обычного метода bind() или с помощью свойств обработчиков событий объекта с параметрами, который передается методу виджета. В первом аргументе этим обработчикам, как обычно, передается объект Event. Некоторые виджеты во втором аргументе передают обработчикам объект «пользовательского интерфейса». Этот объект, как правило, хранит информацию о состоянии виджета.

Обратите внимание, что в документации к библиотеке jQuery UI иногда описываются «события», которые не являются настоящими событиями и являются скорее функциями обратного вызова, которые устанавливаются посредством объекта с параметрами настройки. Например, виджет выбора даты поддерживает несколько функций обратного вызова, которые вызываются им в различных ситуациях. Однако ни одна из этих функций не имеет сигнатуры, свойственной стандартным обработчикам событий, и обработчики этих «событий» нельзя зарегистрировать с помощью метода bind(). Вместо этого соответствующие функции обратного вызова необходимо указывать при настройке виджета в первом вызове метода datepicker().