JavaScript в кайфБорис Вольфсон Хакер, номер #101, стр. 128 (borisvolfson@gmail.com, http://splendot.com) Возможности могучего фреймворка jQuery для веб-программистовИсходники написаны на трех «языках»: HTML, CSS и JavaScript по возможности надо сохранить название языка, на котором они написаны (или цветом выделить). Кроме изображений в формате BMP, я вложил и «исходники» - PSD и VSD на случай, если не устроит качество или размер BMP. Порой в процессе программирования у меня создается впечатление, что jQuery читает мои мысли – так мало кода приходится писать. При этом код не теряет ясности и наглядности, а в простейших случаях напоминает CSS. Точки над «i»?«Разве не программированием мы занимались в прошлой статье? - спросит внимательный читатель. - Ведь мы писали код на JavaScript… неужели это не программирование?» С технической точки зрения - да, с концептуальной – нет. Ведь мы использовали jQuery для верстки, а под программированием стоит понимать более широкий фронт деятельности: от обработки событий до работы с формами. Так что переходим к самому интересному - программированию на JavaScript с использованием jQuery. Если, с точки зрения верстальщика, этот фреймворк - расширение CSS, то программист на JavaScript рассматривает его как на библиотеку доступа к произвольным элементам веб-страницы. От верстки к кодингуЧтобы плавно перейти от верстки к программированию, рассмотрим смежный пример – раскрывающееся вертикальное меню. Существуют целые библиотеки, которые создают подобные меню, а мы управимся парой строчек на JavaScript. Меню будет представлять собой многоуровневый список: Многоуровневое меню
<ul> <li> <div class="collapsible">Первый пункт</div> <ul> <li> <div class="collapsible">Первый подпункт</div> <ul> <li>Первый подпункт</li> <li>Второй подпункт</li> <li>Третий подпункт</li> </ul> </li> </ul> </li> </ul> Как видишь, я использовал слои с классом collapsible, обозначающие «кнопки», при клике на которые меню свернется: Сворачивание меню
$(".collapsible").click(function() { $(this).parent().children().not(".collapsible").toggle(); }); Здесь используется классический прием jQuery – цепочка вызовов. Первой в ней идет конструкция $(this), обозначающая текущий элемент, на котором сработало событие – клик мышкой. Parent() выбирает прямого родителя (в нашем случае тэг li. children()) и, как не сложно догадаться, служит для получения всех дочерних элементов. Из них нам надо убрать слой с классом collapsible, что делает метод not. Теперь осталось вызвать toggle, который либо спрячет, либо покажет ветку меню, в зависимости от ее видимости. Свежие новостиВозможно, этот код покажется тебе несколько усложненным, но зато мы легко сможем использовать его и при создании раскрывающихся новостей. Например, у нас есть заголовки или краткий вариант сообщения; пользователь щелкает по нему и получает открывшуюся новость . Стрелкой я показал, как именно новость будет открываться. Теперь напишем HTML, который будет похож на наше меню: Описание одной новости
<div class="collapsible">Заголовок новости</div> <div> Текст новости </div> </div> JavaScript будет тем же самым, разве что я добавлю в него немного наворотов, которые сделают код более юзабельным. Применим анимацию «разворачивание», которая реализуется методом slideToggle с параметром “slow”, чтобы действие происходило медленно. При загрузке страницы свернем все новости и припишем к заголовку на три символа больше. На практике эти три символа лучше заменить картинкой. Сворачивания/разворачивания новостей
$(".collapsible").click(function() { $(this).parent().children().not(".collapsible").slideToggle("slow"); }); $(".collapsible").parent().children().not(".collapsible").hide(); $(".collapsible").append("<small> >>></small>"); Анимация«Что может быть бесполезней, чем всякая анимация на сайте?» - думал я в детстве. На первый взгляд, подобные мысли кажутся логичными. Но тогда зачем в состав фреймворка (каркаса) включили такой функционал? В нем должно быть только самое нужное, все остальное надо вынести в плагины! Но если посмотреть на любой современный динамический сайт, особенно с применением идеологии AJAX, то станет понятно, что анимация может быть и полезна. Когда добавляется новое сообщение в чате или приходит новое письмо в почтовой системе, посетителю надо ясно указать на эти события. Почтовую систему мы писать не будем, а как работает метод animate, посмотрим на более простом примере. При клике пользователя по кнопке удалим все параграфы – содержимое тэгов p. Если вызывать метод hide, то посетитель не поймет, что произошло («Бац, и все исчезло!»). Мы же плавно погасим текст, уменьшая (по правде говоря, увеличивая) его прозрачность. Чтобы использовать метод animate, ему надо передать два параметра. Первый – это массив изменяющихся свойств, второй – скорость изменения: Анимация: затухание текста
$("#hide").click(function() { $("p").animate({ opacity: 'hide' }, 5000); }); ТултипыВ продолжение темы анимации рассмотрим два специализированных метода - slideDown и slideUp - для сворачивания и разворачивания элементов соответственно. Именно при помощи этих эффектов и будут появляться наши всплывающие подсказки. Определим, что тултипом у нас будет элемент, который следует за ссылкой и имеет класс tooltip. Подсказка может содержать информацию о ресурсе, на который она ведет, что поможет посетителю принять решение о том, стоит ли по ней переходить. Показывать мы ее будем при наведенном на ссылку курсоре . Чтобы обработать событие hover, надо указать две функции, которые будут вызваны при входе курсора мышки в область элемента и выходе из нее: Показываем тултип
$(".tooltip").prev("a").hover( function() { $(this).next(".tooltip").slideDown(); }, function() { $(this).next(".tooltip").slideUp(); } ); Здесь мы использовали новые методы prev и next, которые возвращают предыдущий и последующий элементы соответственно. Последним будет примечание о необходимости скрыть все тултипы при загрузке страницы. Если ты дочитал до этого момента, то знаешь, как это сделать. КлассыПереходим к одной из фундаментальных возможностей в арсенале jQuery – к работе с классами. Для манипуляций с ними нам доступно три основных функции: НАЗВАНИЕ: Функции манипулирования классами
Давай сделаем более юзабельной кнопочку типа submit, которая отправляет форму на сервер. Очень бы хотелось сделать ее недоступной после первичного обращения к ней, чтобы пользователь не отправлял сообщение несколько раз подряд, ведь бывают нервные юзеры ;). Чтобы этого добиться, надо изменить атрибут disabled. Однако мои эстетические воззрения требуют еще и поменять визуальное изображение нажатой кнопки, например изменить фон, границу или надпись. Нам необходимо определить в CSS два класса - enabled и disabled. По умолчанию у кнопки будет класс enabled, а после нажатия - disabled: Меняем класс у нажатой кнопки
$("#submit-button").click( function() { $(this).attr({disabled : "true"}); $("#submit-button").addClass("disabled"); }); РолловерСередина статьи уже далеко позади, поэтому хотелось бы рассмотреть комплексный пример. В качестве него мы сделаем полноценный ролловер. Для самых маленьких читателей поясню, что rollover – это такая красивая кнопочка, которую можно нажать. Но не только: при наведении на нее курсора мышки и нажатии, изображение на кнопке меняется . Договоримся о том, в каких файлах у нас будут храниться эти изображения:НАЗВАНИЕ: Суффиксы имен файлов для ролловера
Чтобы внести ясность, приведу конкретный пример. Если основной файл называется button.jpg, то вспомогательные будут именоваться button_hover.jpg и button_click.jpg. Реализовывать ролловер на HTML будем с помощью тэга ввода с типом «изображение»:<input type="image" src="button.jpg" />. Теперь проясняется механизм работы самого скрипта: нам надо найти все элементы input с типом image и в зависимости от события поменять атрибут src. Поскольку смена имени файла будет происходить при трех событиях, вынесем этот функционал в отдельную функцию changeFilename: Меняем имя файла
function changeFilename(input, count, suffix) { var filename = $(input).attr("src"); filename = filename.substr(0, filename.length-count); filename = filename + suffix + ".jpg"; $(input).attr( {src: filename} ); } Если присмотреться, то легко заметить, что эта функция берет значение атрибута src из элемента input, отрезает от имени файла count символов и добавляет suffix плюс расширение «.jpg». Фактически она меняет один суффикс (конец имени) файла на другой. Теперь осталось грамотно применить эту функцию. Для выбора нужных элементов будем использовать конструкцию $("input[@type=image]"), которая найдет все инпуты с типом image. При наведении курсора мышки на ролловер, нам надо отрезать «.jpg» (4 символа) от имени файла и добавить «_hover.jpg». Вернуть все надо, когда мышка над другим элементом. Меняем изображение при наведении мышки
$("input[@type=image]").hover( function() { changeFilename(this, 4, "_hover"); }, function() { changeFilename(this, 10, ""); } ); Написать обработчик нажатия мышки тоже труда не составит. В качестве события я выбрал mousedown, вместо click. Честно говоря, хотел показать, что не кликом единым живы ;). От имени файла надо откромсать «_hover.jpg» (мышка наведена), то есть 10 символов, и дописать «_click.jpg»: Меняем изображение по клику мышкой
$("input[@type=image]").mousedown(function() { changeFilename(this, 10, "_click"); }); Отмечу, что ролловер у нас получился довольно универсальный. Чтобы применить его, надо создать три файла, которые соответствуют состояниям кнопки, и использовать элемент input с атрибутом image. Неплохо для десятка строчек кода ;). «Вордатор»На десерт осталось уже настоящее веб-приложение – «Вордатор». Оно будет очищать HTML от лишнего кода, вставленного визуальными редакторами, например Word’ом. Интерфейс у нас будет несложным, поскольку нам требуется всего лишь два поля ввода и переключатели опций . Чтобы создать такую форму, проще всего воспользоваться таблицами. С этим, я думаю, проблем не возникнет. Для описания отдельных элементов надо использовать традиционные тэги HTML: label, textarea, input, button. Необходимо обязательно прописать идентификаторы элементов, чтобы мы смогли обрабатывать события и получать содержимое элементов. Приведу описание нашей формы без таблиц разметки: Элементы формы без разметки
<label>HTML для очистки <textarea id="source" cols="80" rows="10"></textarea> </label> <label>Теги <input id="tagsToClean" type="text" /> </label> <label>Атрибуты <input id="attrsToClean" type="text" /> </label> <label>Зачищенный HTML <textarea id="result" cols="80" rows="10"></textarea> </label> <button id="clean">Очистить</button> Как видишь, функциональность небольшая, но нам достаточная. Мы будем удалять ненужные атрибуты и очищать бесполезные пустые тэги. Первое действие я подробно распишу, так как на его примере можно посмотреть, как парсить HTML с помощью jQuery. Прежде всего надо получить текст из поля ввода с идентификатором source. Затем нужно получить (чем заменить это получить? Ммм… взять?) на его основе объект jQuery. Я сделал это с помощью невидимого контейнера resdiv. Оформить это лучше в виде отдельной функции getUserHtml(): Тело функции getUserHtml()
$(document.body).append("<div style=\"display: none\" id=\"resdiv\"><div>"); var htmlToClean = $("#source").val(); $("#resdiv").html(htmlToClean); Для парсинга HTML мы, разумеется, воспользуемся функцией $(…), но искать объекты нам надо не по всему документы, а только в контейнере resdiv, поэтому обязательно придется указать второй параметр у функции $(…) в качестве контекста поиска. Осталось уточнить, что работать со значением элементов форм нужно методом val(), а весь код необходимо поместить в конструкцию $(document).ready: Тело функции getUserHtml()
$("#clean").click(function() { getUserHtml(); $("*", $("#resdiv")).each( function() { attrsToClean = $("#attrsToClean").val().split(" ") for (attr in attrsToClean) { $(this).removeAttr(attrsToClean[attr]); } }); $("#result").val($("#resdiv").html()); return false; }); Итак, что же мы натворили нашими программистскими руками? Сперва мы повесили обработчик клика на кнопку «Очистить». В нем мы вызываем функцию getUserHtml, которую описали выше. Далее мы находим все HTML элементы в контейнере resdiv. Для извлечения строки атрибутов из поля ввода attrsToClean используем метод val() и разбиваем атрибуты пробелами. Пробегаясь по всем атрибутам из списка, удаляем их. Результат помещаем в поле ввода result. И все! Удалять стоит атрибуты lang, style и class. Также можно посмотреть, какие атрибуты любит добавлять твой визуальный редактор. Что касается ненужных тэгов, например, span после Word’а, то их проще всего удалять регулярными выражениями. Это и останется тебе на самостоятельную работу, потому что к jQuery имеет мало отношения ;). ЗаканчиваемУх, много дел свершено, мало кода написано, лепота! Надеюсь, мне удалось не только объяснить основные принципы фреймворка jQuery, но и показать на конкретных примерах, как написать приложения. Вторая моя надежда связана с тобой: попробуй написать код из статей (или, в крайнем случае, возьми его с диска) и используй его у себя на сайте или блоге. Философское отступление, или мысли программиста вслухПоследствия применения jQuery в качестве фреймворка при разработке веб-приложений на стороне клиента сразу бросаются в глаза. HTML-код становится чистым, кристально чистым, как в рекламе стирального порошка :). Это происходит, во-первых, из-за отсутствия необходимости прописывать события внутри HTML-кода, а во-вторых, из-за отсутствия «лишних» классов, которые могут быть добавлены динамически. Тем не менее, всегда могут пострадать пользователи с отключенным JavaScript. И последнее, что стоит отметить, - это отсутствие HTML для декорирования. Ярким примером может быть создание скругленных уголков у элементов, когда при обычном подходе используются вложенные контейнеры. Следующее, что бросается в глаза, - это уменьшение количества кода. Тут в первую очередь играет роль мощный механизм поиска нужных элементов. И, конечно же, нельзя забыть об автоматизации множества рутинных действий с помощью фреймворка jQuery.
|