Когда 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 предлагает следующий способ: Code (function($) {
})(jQuery);
Повсеместное использование $ в jQuery не более, чем хитроумный трюк. Но если рассматривать его только в контексте jQuery, то такое решение выглядит очень гибким.
Выбираем элементыКаждый jQuery-оператор начинается с выбора одного или нескольких узлов DOM. Синтаксис селекторов jQuery (внутренний язык этой библиотеки) является интересным гибридом спецификаций CSS 1, 2, немного CSS 3, немного XPath и еще малость других расширений. Не будем углубляться в детали, просто приведем несколько полезных примеров: Code jQuery('div.panel')
jQuery('p#intro')
jQuery('div#content a:visible')
jQuery('input[@name=email]')
jQuery('table.orders tr:odd')
jQuery('a[@href^="http://"]')
jQuery('p[a]')
Наибольший интерес из вышеописанного представляют :visible и :odd, которые являются специфичными только для jQuery. Стоит также отметить, что выбор атрибутов использует знак @, что более соответствует XPath нежели CSS 2. Язык селекторов весьма богат и очень похож на регулярные выражения, так что время, потраченное на его изучение, окупится сполна.
Чего-нибудь с ними делаемОбъект, который возвращают селекторы jQuery, является довольно интересным зверем. Он представляет собой набор DOM-элементов и ведет себя немного как массив: у него есть свойство length, к его элементам можно получить доступ по индексу и (что более важно) Firebug расценивает его именно как массив при отображении в своей консоли. Это не более, чем красивая иллюзия: набор элементов, на самом деле, - это объект jQuery, у которого есть большое число методов для выбора, изменения или расширения имеющегося набора. В jQuery имеется три разных категории методов: первые манипулируют со всеми элементами, которые подходят по шаблону, вторые возвращают значение от первого найденного элемента, и третьи изменяют саму выборку. Не будем перечислять все доступные методы (это можно посмотреть и на visualjquery.com), но приведем некоторые примеры. Если у вас есть Firebug, вы можете попробовать их самостоятельно: просто нужно воспользоваться закладкой «Вставить jQuery» Code (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 в конце (чтобы на страницу не выводилось возвращаемое значение)). Code jQuery('div#primary').width(300);
jQuery('p').css('line-height', '1.8em');
jQuery('li:odd').css({color: 'white', backgroundColor: 'black'});
jQuery('a[@href^="http://"]').addClass('external').attr('target', '_blank');
jQuery('blockquote').each(function(el) { alert(jQuery(this).text()) });
jQuery('a').html('Нажми здесь!');
var width = jQuery('div').width();
var src = jQuery('img').attr('src');
var color = jQuery('h1').css('color');
Отметим удобную симметрию таких методов: они используются как для выставления атрибутов (когда принимают 2 аргумента или у передаваемого объекта несколько свойств), так и для прочтения значений этих атрибутов (если передается только один аргумент). Такая симметрия используется во всей библиотеке jQuery, что очень сильно облегчает запоминание API. Также есть несколько методов, которые изменяют весь набор найденных элементов. Многие из них также обеспечивают перемещение по DOM-дереву: Code jQuery('div').not('[@id]')
jQuery('h2').parent()
jQuery('blockquote').children()
jQuery('p').eq(4).next()
jQuery('input:text:first').parents('form')
Цепочки вызововКоманда разработчиков jQuery часто гордятся поддержкой в этой библиотеке цепочки вызовов, доходя до заявлений типа «jQuery создана для того, чтобы изменить ваш стиль программирования на JavaScript» прямо на главной странице. Эту технику находят скорее боковым ответвлением, чем дорогой в будущее, но вы можете использовать jQuery, избежав длинных цепочек вызовов. Цепочки можно использовать для нескольких интересных трюков. В дополнение к использованию набора DOM-выборок вы можете применить jQuery-метод end() для перемещения по стеку объектов и выхода из текущего контекста. Это немного сложно объяснить, но когда вы используете метод, который изменяет текущий (объектный) контекст (например, children() или filter()), вы можете использовать end() чуть позже, чтобы вернуться к предыдущей выборке. Jesse Skinner приводит хороший пример использования этой возможности в своем учебнике «Делаем разработку на AJAX проще с jQuery»: Code $('form#login')
.find('label.optional').hide().end()
.find('input:password').css('border', '1px solid red').end()
.submit(function(){ return confirm('Вы действительно хотите отправить данные?'); });
Все это большое преобразование займет всего одну строку. Оно находит форму, находит некоторые элементы внутри нее, применяет к ним изменения, возвращается обратно к форме и добавляет к ней обработчик события submit().
Манипулируем с DOMВ jQuery имеется несколько способов для объемных манипуляций с DOM. Первый является несколько неожиданным: функция jQuery может принимать в качестве аргумента кусок HTML-кода, который преобразуется в DOM-элемент (фактически, это просто строка): Code var div = jQuery('Some text');
Можно использовать цепочку вызовов, чтобы добавить атрибуты к div , как только он был создан: Code 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(), методы для событий могут служить двум целям: их вызов с функцией в качестве аргумента назначает обработчик события, вызов без аргумента эмулирует возникновение этого события: Code jQuery('p').click(function() { jQuery(this).css('background-color', 'red'); });
jQuery('p:first').click()
jQuery('a').hover(function() { jQuery(this).css('background-color', 'orange'); }, function() { jQuery(this).css('background-color', 'white'); });
jQuery('p').one('click', function() { alert(jQuery(this).html()); });
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 уже будет к ней готов: Code jQuery(document).ready(function() { alert('DOM готов!'); });
И даже больше, вы можете сократить эту запись, назначив вашу функцию напрямую jQuery(): Code jQuery(function() { alert('DOM готов!'); });
jQuery и AJAXУ jQuery лучший API для работы с AJAX, который я когда-либо видел в больших библиотеках. Наиболее простая форма AJAX-вызова выглядит следующим образом: Code jQuery('div#intro').load('/some/fragment.html');
Он выполнит GET-запрос к /some/fragment.html и вставит в div#intro HTML-код, который получит. Что если требуется что-то более сложное, например, вывести индикатор AJAX-загрузки? jQuery предоставляет набор собственных событий (ajaxStart, ajaxComplete, ajaxError и другие) для использования в случае необходимости. Также в этой библиотеки есть и более продвинутый API низкого уровня для сложных AJAX-взаимодействий: Code jQuery.get('/some/script.php', {'name': 'Simon'}, function(data) { alert('Сервер ответил: ' + data); });
jQuery.post('/some/script.php', {'name': 'Simon'}, function(data) { alert('Сервер ответил: ' + data); });
jQuery.getJSON('/some.json', function(json) { alert('JSON выдал: ' + json.foo + ' ' + json.bar); });
jQuery.getScript('/script.js');
РасширенияРассматривая весь этот набор функций в стандартной поставке, стоит заметить, что ужатый вариант jQuery занимает всего 20 КБ, и даже еще меньше, если применить архивирование (.gz). Дополнительная функциональность, выходящая за пределы это поставки, может быть организована с помощью расширений, которые могут (и так и делают) добавить новые методы к существующему объекту jQuery. При желании можно выполнить что-то вроде этого: Code jQuery('p').bounceAroundTheScreenAndTurnGreen();
Механизм расширений в jQuery обеспечивает задокументированные методы для их добавления в систему. Простота и удобство их использования привлекли большое сообщество авторов таких расширений; справочник расширений насчитывает уже более ста примеров. Еще одной приятной особенностью является возможность добавлять собственные селекторы так же, как и собственные методы. Расширение moreSelectors добавляет методы типа div:color(red), который, например, выбирает все div с красным текстом. В качестве заключенияЗдесь высказано достаточно фактов для положительного заключения по поводу jQuery, что она не является очередной библиотекой. В ней заложена масса интересных идей, которые способны удивить даже достаточно опытных JavaScript-программистов и научить их чему-то новому. Даже если вы не будете использовать ее в своей работе, стоит посвятить некоторое время и исследовать «экосистему» jQuery.
|