Распечатать статью

jQuery для JavaScript

Когда jQuery, библиотека JavaScript, увидела свет в январе 2006, все подумали: «очередная красивая игрушка». Выбор CSS-селекторов в качестве базиса было, конечно, изящной идеей, но использование цепочек преобразований выглядело немного замысловато, и сама библиотека, по-видимому, не покрывала всех возможных случаев. jQuery расценивали тогда только как временное и проходящее решение.

Только несколько месяцев спустя стало понятно, что jQuery является просто произведением инженерного искусства. Она умело покрывает достаточно широкий диапазон повседневных функций и предоставляет при этом удобный API для расширений, с помощью которых можно добавить любую другую функциональность. Абстрактность в ней заложена на уровне ядра — речь идет о выборе элементов объектной модели документов (DOM) — и она извлекает из него максимум пользы. И что важнее всего, использование этой библиотеки подразумевает следование хорошему стилю в программировании и хорошо сочетается с другими частями JavaScript-кода.

Большинство современных обзоров jQuery делают упор на дизайнеров и неопытных разработчиков. Я попытаюсь объяснить, почему она также нужна и опытным программистам.

Пространство имен (namespacing)

Ключевым моментом в создании хорошего JavaScript-кода для дальнейшего использования является тщательное управление пространством имен. В JavaScript существует единое глобальное пространство имен (объект window), и многие программисты (и даже некоторые библиотеки) засоряют его безо всякой надобности. Глобальные переменные — зло! Более благоразумные разработчики сводят к минимуму свое вторжение в это пространство, используя некоторые методы, например, модульную модель.
jQuery вводит единственный объект в глобальное пространство имен — функцию/объект jQuery. Все остальное — это либо непосредственное свойство jQuery, либо метод объекта, возвращаемого вызовом функции jQuery.

Что можно сказать об улучшениях языка? Большинство библиотек предоставляют некоторое подобие функций отображения, фильтрации и обрезания, которые, к несчастью, отсутствуют в тех движках JavaScript, которые включены в большинство браузеров. Некоторые библиотеки напрямую расширяют встроенные в JavaScript классы String и Array, но также не до конца безопасно. String.prototype и Array.prototype являются самостоятельными глобальными пространствами имен, и добавление в них каких-либо свойств влечет опасность коллизий, связанных с использованием одних и тех же имен переменных в разных контекстах.

В jQuery имеется некоторое количество функций, расширяющих возможность JavaScript, но каждая из них является доступной только как свойство объекта jQuery: jQuery.each, jQuery.extend, jQuery.grep, jQuery.map, jQuery.merge и jQuery.trim. Они по определению не будут конфликтовать с каким-либо другим кодом.

Печально известная функция $
На самом деле jQuery вводит не один символ в глобальное пространство имен, есть еще и $: он используется как сокращение для jQuery. Это производится достаточно мягко: если вам снова требуется ваша прежняя функция $ (например, если у вас есть часть кода, основанная на Prototype), вы можете вызвать jQuery.noConflict(), чтобы вернуть свою старую функцию $.
Если вам требуется ограничить использование функции $ для jQuery не опасаясь коллизий при каком-либо другом использовании глобальной функции $, документация по jQuery предлагает следующий способ:

(function($) { // Внутри этого блока $ относится к jQuery // Изящно, правда? })(jQuery);

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

Выбираем элементы
Каждый jQuery-оператор начинается с выбора одного или нескольких узлов DOM. Синтаксис селекторов jQuery (внутренний язык этой библиотеки) является интересным гибридом спецификаций CSS 1, 2, немного CSS 3, немного XPath и еще малость других расширений. Не будем углубляться в детали, просто приведем несколько полезных примеров:

• jQuery('div.panel') Все div с class="panel" • jQuery('p#intro') Параграф с id="intro" • jQuery('div#content a:visible') Все видимые ссылки внутри div с id="content" • jQuery('input[@name=email]') Все поля ввода с name="email" • jQuery('table.orders tr:odd') Все четные строки в таблице с class="orders" • jQuery('a[@href^="http://"]') Все внешние ссылки (те, которые начинаются с http://) • jQuery('p[a]') Все параграфы, в которых есть хотя бы одна ссылка

Наибольший интерес из вышеописанного представляют :visible и :odd, которые являются специфичными только для jQuery. Стоит также отметить, что выбор атрибутов использует знак @, что более соответствует XPath нежели CSS 2.

Язык селекторов весьма богат и очень похож на регулярные выражения, так что время, потраченное на его изучение, окупится сполна.

Чего-нибудь с ними делаем
Объект, который возвращают селекторы jQuery, является довольно интересным зверем. Он представляет собой набор DOM-элементов и ведет себя немного как массив: у него есть свойство length, к его элементам можно получить доступ по индексу и (что более важно) Firebug расценивает его именно как массив при отображении в своей консоли. Это не более, чем красивая иллюзия: набор элементов, на самом деле, — это объект jQuery, у которого есть большое число методов для выбора, изменения или расширения имеющегося набора.
В jQuery имеется три разных категории методов: первые манипулируют со всеми элементами, которые подходят по шаблону, вторые возвращают значение от первого найденного элемента, и третьи изменяют саму выборку.

Не будем перечислять все доступные методы (это можно посмотреть и на visualjquery.com), но приведем некоторые примеры. Если у вас есть Firebug, вы можете попробовать их самостоятельно: просто нужно воспользоваться закладкой «Вставить jQuery» (javascript:void(function(){var s=document.createElement(‘script’);
s.src=’http://code.jquery.com/jquery-1.1.2.js'; document.getElementsByTagName(‘head’)[0].appendChild(s);}())) для загрузки самой библиотеки для любой страницы, а затем вставить примеры кода в консоль Firebug (прим.: можно и без Firebug: достаточно загрузить jQuery с помощью указанной ссылки и вызвать приведенные примеры в адресной строке браузера, не забыв в начале javascript: и какой-либо alert в конце (чтобы на страницу не выводилось возвращаемое значение)).

• jQuery('div#primary').width(300); Выставляет ширину div id="primary" в 300 пикселей. • jQuery('p').css('line-height', '1.8em'); Выставляет высоту строки в 1.8em для всех параграфов. • jQuery('li:odd').css({color: 'white', backgroundColor: 'black'}); Применяет 2 CSS-правила для каждого пункта списка; заметьте, что функция css() может принимать объект таблицы стилей вместо двух строк. • jQuery('a[@href^="http://"]').addClass('external').attr('target', '_blank'); Добавляет класс "external" для всех внешних ссылок (тех, что начинаются с http://), затем добавляет target="_blank", чтобы увеличить различие. В данном примере используется цепочка вызовов, описанная ниже. • jQuery('blockquote').each(function(el) { alert(jQuery(this).text()) }); Для каждого тега blockquote на странице выводит сообщение (alert) с его текстовым содержанием (включая HTML-теги). • jQuery('a').html('Нажми здесь!'); Заменяет весь текст в ссылках на странице призывом «Нажми здесь!». Ниже несколько примеров методов, которые возвращают значение от первого элемента, найденного по шаблону: • var width = jQuery('div').width(); Какая ширина у первого div на странице? • var src = jQuery('img').attr('src'); Какое значение у атрибута src у первой картинки на странице? • var color = jQuery('h1').css('color'); Какой цвет у первого h1?

Отметим удобную симметрию таких методов: они используются как для выставления атрибутов (когда принимают 2 аргумента или у передаваемого объекта несколько свойств), так и для прочтения значений этих атрибутов (если передается только один аргумент). Такая симметрия используется во всей библиотеке jQuery, что очень сильно облегчает запоминание API.
Также есть несколько методов, которые изменяют весь набор найденных элементов. Многие из них также обеспечивают перемещение по DOM-дереву:

• jQuery('div').not('[@id]') Возвращает все div, у которых нет атрибута id. • jQuery('h2').parent() Возвращает все элементы, которые являются непосредственными родителями h2. • jQuery('blockquote').children() Возвращает все элементы, вложенные в blockquote. • jQuery('p').eq(4).next() Находит пятый параграф на странице, потом находит следующий элемент (т.е. непосредственного соседа справа). • jQuery('input:text:first').parents('form') Находит родительский элемент для формы, которая содержит первое поле input type="text" на странице. Опциональным параметром для parents() является другой селектор.

 

Цепочки вызовов

Команда разработчиков jQuery часто гордятся поддержкой в этой библиотеке цепочки вызовов, доходя до заявлений типа «jQuery создана для того, чтобы изменить ваш стиль программирования на JavaScript» прямо на главной странице. Эту технику находят скорее боковым ответвлением, чем дорогой в будущее, но вы можете использовать jQuery, избежав длинных цепочек вызовов.
Цепочки можно использовать для нескольких интересных трюков. В дополнение к использованию набора DOM-выборок вы можете применить jQuery-метод end() для перемещения по стеку объектов и выхода из текущего контекста. Это немного сложно объяснить, но когда вы используете метод, который изменяет текущий (объектный) контекст (например, children() или filter()), вы можете использовать end() чуть позже, чтобы вернуться к предыдущей выборке. Jesse Skinner приводит хороший пример использования этой возможности в своем учебнике Делаем разработку на AJAX проще с jQuery:

$('form#login') // прячем внутри формы все label с классом optional .find('label.optional').hide().end() // добавляем красную границу ко всем полям типа password в форме .find('input:password').css('border', '1px solid red').end() // добавляем обработчик на событие submit для формы .submit(function(){ return confirm('Вы действительно хотите отправить данные?'); });

Все это большое преобразование займет всего одну строку. Оно находит форму, находит некоторые элементы внутри нее, применяет к ним изменения, возвращается обратно к форме и добавляет к ней обработчик события submit().

Манипулируем с DOM

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

var div = jQuery(' Some text ');

Можно использовать цепочку вызовов, чтобы добавить атрибуты к div, как только он был создан:

var div = jQuery('<div>Some text</div>').addClass('inserted').attr('id', 'foo'); Теперь добавим его к тегу body: div.appendTo(document.body) Или вставим его, используя селектор, в имеющийся код: div.prependTo('div#primary')

 

Перехватываем события

Все JavaScript-библиотеки нуждаются в методах для обработки событий, и jQuery не является исключением. Как и в случае attr() и css(), методы для событий могут служить двум целям: их вызов с функцией в качестве аргумента назначает обработчик события, вызов без аргумента эмулирует возникновение этого события:

• jQuery('p').click(function() { jQuery(this).css('background-color', 'red'); }); Выставляем для всех параграфов обработчик клика мыши, по которому они становятся красными. • jQuery('p:first').click() Эмулируем клик для первого параграфа на странице. Похожие функции используются для других событий браузера: mouseover, keyup и т.д. Следует заметить, что при вызове обработчика событий ключевое слово this ссылается на элемент, который это событие вызвал; использование jQuery(this) является расхожим приемом, чтобы вызвать методы jQuery для этого элемента. Пара функций, относящихся к событиям, заслуживает отдельного упоминания: jQuery('a').hover(function() { jQuery(this).css('background-color', 'orange'); }, function() { jQuery(this).css('background-color', 'white'); }); hover() является сокращением для сразу двух событий: onmouseover и onmouseout. jQuery('p').one('click', function() { alert(jQuery(this).html()); }); one() выставляет обработчик событий, который будет удален после первого своего вызова. В вышеприведенном примере всем параграфы должны сообщить (alert) свое содержание после первого клика по ним. jQuery также поддерживает собственные события через методы bind() и trigger() (подобные click()). Собственные события могут принимать аргументы, передаваемые при помощи массива в вызове trigger(): jQuery(document).bind('stuffHappened', function(event, msg) { alert('Что прозошло: ' + msg); }); jQuery(document).trigger('stuffHappened', ['Привет!']);

 

Ненавязчивое (unobtrusive) программирование

Лучшие веб-приложения — это те, которые могут функционировать и при отключенных скриптах, и лучшим методом для достижения этой цели будет ненавязчивый JavaScript, когда события назначаются элементам только после того, как вся HTML-страница у пользователя загрузится (для более подробной информации можно ознакомиться с ненавязчивым программированием и Hijax).
В jQuery присутствует замечательная поддержка этого подхода. Во-первых, парадигма селекторов для выбора узла является основополагающей как для jQuery, так и для ненавязчивого программирования в целом. Во-вторых, jQuery обеспечивает решения для проблемы window.onload, основанной на исследованиях Dean Edwards по поводу работы события «DOM loaded» для различных браузеров. Вы можете выставить функцию-обработчик тогда, когда DOM уже будет к ней готов:

jQuery(document).ready(function() { alert('DOM готов!'); });

И даже больше, вы можете сократить эту запись, назначив вашу функцию напрямую jQuery():

jQuery(function() { alert('DOM готов!'); });

 

jQuery и AJAX

У jQuery лучший API для работы с AJAX, который я когда-либо видел в больших библиотеках. Наиболее простая форма AJAX-вызова выглядит следующим образом:
jQuery(‘div#intro’).load(‘/some/fragment.html’);

Он выполнит GET-запрос к /some/fragment.html и вставит в div#intro HTML-код, который получит.
Что если требуется что-то более сложное, например, вывести индикатор AJAX-загрузки? jQuery предоставляет набор собственных событий (ajaxStart, ajaxComplete, ajaxError и другие) для использования в случае необходимости. Также в этой библиотеки есть и более продвинутый API низкого уровня для сложных AJAX-взаимодействий:

jQuery.get('/some/script.php', {'name': 'Simon'}, function(data) { alert('Сервер ответил: ' + data); }); // GET-запрос к /some/script.php?name=Simon jQuery.post('/some/script.php', {'name': 'Simon'}, function(data) { alert('Сервер ответил: ' + data); }); // POST-запрос к /some/script.php jQuery.getJSON('/some.json', function(json) { alert('JSON выдал: ' + json.foo + ' ' + json.bar); }); // Возвращает и преобразует ответ от /some.json как JSON jQuery.getScript('/script.js'); // GET-запрос к /script.js и eval()

 

Расширения

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

jQuery('p').bounceAroundTheScreenAndTurnGreen();

Механизм расширений в jQuery обеспечивает задокументированные методы для их добавления в систему. Простота и удобство их использования привлекли большое сообщество авторов таких расширений; справочник расширений насчитывает уже более ста примеров.
Еще одной приятной особенностью является возможность добавлять собственные селекторы так же, как и собственные методы. Расширение moreSelectors добавляет методы типа div:color(red), который, например, выбирает все div с красным текстом.

В качестве заключения

Здесь высказано достаточно фактов для положительного заключения по поводу jQuery, что она не является очередной библиотекой. В ней заложена масса интересных идей, которые способны удивить даже достаточно опытных JavaScript-программистов и научить их чему-то новому. Даже если вы не будете использовать ее в своей работе, стоит посвятить некоторое время и исследовать «экосистему» jQuery.

Источник:  internet-technologies.ru

Вы можете оставить комментарий, или обратную ссылку на Ваш сайт.

Оставить комментарий

Похожие статьи