Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #101, МАЙ 2007 г.

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. Меню будет представлять собой многоуровневый список:

Многоуровневое меню

  • ЯЗЫК: HTML

<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, обозначающие «кнопки», при клике на которые меню свернется:

Сворачивание меню

  • ЯЗЫК: JavaScript

$(".collapsible").click(function() {

$(this).parent().children().not(".collapsible").toggle();

});

Здесь используется классический прием jQuery – цепочка вызовов. Первой в ней идет конструкция $(this), обозначающая текущий элемент, на котором сработало событие – клик мышкой. Parent() выбирает прямого родителя (в нашем случае тэг li. children()) и, как не сложно догадаться, служит для получения всех дочерних элементов. Из них нам надо убрать слой с классом collapsible, что делает метод not. Теперь осталось вызвать toggle, который либо спрячет, либо покажет ветку меню, в зависимости от ее видимости.

Свежие новости

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

Стрелкой я показал, как именно новость будет открываться. Теперь напишем HTML, который будет похож на наше меню:

Описание одной новости

  • ЯЗЫК: HTML

<div class="collapsible">Заголовок новости</div>

<div>

Текст новости

</div>

</div>

JavaScript будет тем же самым, разве что я добавлю в него немного наворотов, которые сделают код более юзабельным. Применим анимацию «разворачивание», которая реализуется методом slideToggle с параметром “slow”, чтобы действие происходило медленно. При загрузке страницы свернем все новости и припишем к заголовку на три символа больше. На практике эти три символа лучше заменить картинкой.

Сворачивания/разворачивания новостей

  • ЯЗЫК: JavaScript

$(".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, ему надо передать два параметра. Первый – это массив изменяющихся свойств, второй – скорость изменения:

Анимация: затухание текста

  • ЯЗЫК: JavaScript

$("#hide").click(function() {

$("p").animate({ opacity: 'hide' }, 5000);

});

Тултипы

В продолжение темы анимации рассмотрим два специализированных метода - slideDown и slideUp - для сворачивания и разворачивания элементов соответственно. Именно при помощи этих эффектов и будут появляться наши всплывающие подсказки. Определим, что тултипом у нас будет элемент, который следует за ссылкой и имеет класс tooltip. Подсказка может содержать информацию о ресурсе, на который она ведет, что поможет посетителю принять решение о том, стоит ли по ней переходить. Показывать мы ее будем при наведенном на ссылку курсоре .

Чтобы обработать событие hover, надо указать две функции, которые будут вызваны при входе курсора мышки в область элемента и выходе из нее:

Показываем тултип

  • ЯЗЫК: JavaScript

$(".tooltip").prev("a").hover(

function() { $(this).next(".tooltip").slideDown(); },

function() { $(this).next(".tooltip").slideUp(); }

);

Здесь мы использовали новые методы prev и next, которые возвращают предыдущий и последующий элементы соответственно. Последним будет примечание о необходимости скрыть все тултипы при загрузке страницы. Если ты дочитал до этого момента, то знаешь, как это сделать.

Классы

Переходим к одной из фундаментальных возможностей в арсенале jQuery – к работе с классами. Для манипуляций с ними нам доступно три основных функции:

НАЗВАНИЕ: Функции манипулирования классами

  • addClass – добавляет указанный класс данному элементу
  • removeClass – удаляет указанный класс у данного элемента
  • toggleClass – добавляет или удаляет класс в зависимости от наличия его у элемента

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

Однако мои эстетические воззрения требуют еще и поменять визуальное изображение нажатой кнопки, например изменить фон, границу или надпись. Нам необходимо определить в CSS два класса - enabled и disabled. По умолчанию у кнопки будет класс enabled, а после нажатия - disabled:

Меняем класс у нажатой кнопки

  • ЯЗЫК: JavaScript

$("#submit-button").click( function() {

$(this).attr({disabled : "true"});

$("#submit-button").addClass("disabled");

});

Ролловер

Середина статьи уже далеко позади, поэтому хотелось бы рассмотреть комплексный пример. В качестве него мы сделаем полноценный ролловер. Для самых маленьких читателей поясню, что rollover – это такая красивая кнопочка, которую можно нажать. Но не только: при наведении на нее курсора мышки и нажатии, изображение на кнопке меняется .

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

НАЗВАНИЕ: Суффиксы имен файлов для ролловера

  • .jpg – исходное изображение кнопки
  • _hover.jpg – кнопка при наведении мышки
  • _click.jpg – нажатая кнопка

Чтобы внести ясность, приведу конкретный пример. Если основной файл называется button.jpg, то вспомогательные будут именоваться button_hover.jpg и button_click.jpg.

Реализовывать ролловер на HTML будем с помощью тэга ввода с типом «изображение»:

<input type="image" src="button.jpg" />.

Теперь проясняется механизм работы самого скрипта: нам надо найти все элементы input с типом image и в зависимости от события поменять атрибут src. Поскольку смена имени файла будет происходить при трех событиях, вынесем этот функционал в отдельную функцию changeFilename:

Меняем имя файла

  • ЯЗЫК: JavaScript

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». Вернуть все надо, когда мышка над другим элементом.

Меняем изображение при наведении мышки

  • ЯЗЫК: JavaScript

$("input[@type=image]").hover(

function() { changeFilename(this, 4, "_hover"); },

function() { changeFilename(this, 10, ""); }

);

Написать обработчик нажатия мышки тоже труда не составит. В качестве события я выбрал mousedown, вместо click. Честно говоря, хотел показать, что не кликом единым живы ;). От имени файла надо откромсать «_hover.jpg» (мышка наведена), то есть 10 символов, и дописать «_click.jpg»:

Меняем изображение по клику мышкой

  • ЯЗЫК: JavaScript

$("input[@type=image]").mousedown(function() {

changeFilename(this, 10, "_click");

});

Отмечу, что ролловер у нас получился довольно универсальный. Чтобы применить его, надо создать три файла, которые соответствуют состояниям кнопки, и использовать элемент input с атрибутом image. Неплохо для десятка строчек кода ;).

«Вордатор»

На десерт осталось уже настоящее веб-приложение – «Вордатор». Оно будет очищать HTML от лишнего кода, вставленного визуальными редакторами, например Word’ом. Интерфейс у нас будет несложным, поскольку нам требуется всего лишь два поля ввода и переключатели опций .

Чтобы создать такую форму, проще всего воспользоваться таблицами. С этим, я думаю, проблем не возникнет. Для описания отдельных элементов надо использовать традиционные тэги HTML: label, textarea, input, button. Необходимо обязательно прописать идентификаторы элементов, чтобы мы смогли обрабатывать события и получать содержимое элементов. Приведу описание нашей формы без таблиц разметки:

Элементы формы без разметки

  • ЯЗЫК: HTML

<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()

  • ЯЗЫК: JavaScript

$(document.body).append("<div style=\"display: none\" id=\"resdiv\"><div>");

var htmlToClean = $("#source").val();

$("#resdiv").html(htmlToClean);

Для парсинга HTML мы, разумеется, воспользуемся функцией $(…), но искать объекты нам надо не по всему документы, а только в контейнере resdiv, поэтому обязательно придется указать второй параметр у функции $(…) в качестве контекста поиска. Осталось уточнить, что работать со значением элементов форм нужно методом val(), а весь код необходимо поместить в конструкцию $(document).ready:

Тело функции getUserHtml()

  • ЯЗЫК: JavaScript

$("#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.

  • Конструкция $(document).ready – продвинутый вариант window.onload
  • Метод css используется для установки значений каскадных таблиц стилей
  • Метод attr служит для манипулирования атрибутами HTML-элементов
Содержание