Date post: | 03-Jan-2016 |
Category: |
Documents |
Upload: | marcoci-valeriu |
View: | 260 times |
Download: | 11 times |
О других книгах серии Head First
«В книге „Изучаем объектно-ориентированный анализ и проектирование“ используется новый подход к теме ООАП. Эта книга отличается от других тем, что она ориентирована на об-учение. Авторы сделали материал ООАП доступным и полезным для программиста-прак-тика».
— Айвар Джейкобсон, Ivar Jacobson Consulting
«Я только что закончил читать „Изучаем объектно-ориентированный анализ и проектирование“ и остался в полном восторге! Больше всего мне понравилось то, что книга ориентирована на необходимость применения ООАП для написания хороших программ».
— Кайл Браун, заслуженный инженер, IBM
«За смешными картинками и вычурными шрифтами скрывается серьезное, разумное, ис-ключительно качественно проработанное изложение объектно-ориентированного анали-за и проектирования. Во время чтения книги мне казалось, что я стою за спиной опытного проектировщика, который объясняет мне, какие аспекты важны на каждом этапе проек-тирования, и почему».
— Эдвард Сьоре, адьюнкт-профессор, факультет компьютерных технологий, Бостонский колледж
«В целом „Управление разработкой ПО“ представляет собой замечательный источник инфор-мации для всех, кто хочет привести в порядок свои навыки программирования — причем подход к изложению материала постоянно привлекает внимание читателя на многих уров-нях».
— Энди Хадсон, Linux Format
«Программистам-новичкам „Управление разработкой ПО“ поможет сразу встать на правиль-ный путь. Да и опытные разработчики найдут здесь для себя немало полезного».
— Томас Дафф, Duffbert’s Random Musings
«Вместо изложения материала в стиле традиционных учебников „Программируем для iPhone и iPad“ предлагает читателю живую, увлекательную и даже приятную методику обуче-ния программированию для iOS. Материал подобран умело и качественно: в книге рас-сматриваются многие ключевые технологии, включая Core Data, и даже такие важные аспекты, как проектирование интерфейса. И где еще можно прочитать, как UIWebView и UITextField беседуют у камина?»
— Шон Мерфи, проектировщик и разработчик приложений для iOS
О других книгах серии Head First
«Книга „Программируем для iPhone и iPad“ объясняет принципы разработки приложений iOS с самого начала. Основные изменения по сравнению с первым изданием относятся к iOS 4, Xcode 4 и написанием приложений для iPad. Благодаря пошаговым описаниям с визуаль-ным стилем изложения материала эта книга становится отличным средством изучения программирования для iPhone и iPad во всех аспектах, от простейших до нетривиальных».
— Рич Розен, программист и соавтор книги Mac OS X for Unix Geeks
«Главное достоинство книги — простые, пошаговые описания. Она не пытается научить читателя всему сразу, а знакомит его с построением приложений для iOS на уровне друже-ственного, разговорного общения. Эта книга идеально подходит для людей, которые уже умеют программировать и хотят поскорее заняться построением приложений для iOS».
— Эрик Шеферд, владелец Syndicomm
«Книга „Программируем для iPhone и iPad“ написана специально для того, чтобы научить вас создавать приложения, изучать и использовать технологии iOS без предварительного опыта работы со средствами разработки на Macintosh».
— Джо Хек, основатель Seattle Xcoders
«Эта книга способна вывести из себя! Некоторым из нас пришлось изучать программиро-вание для iOS „классическим“ способом, а теперь вдруг выясняется, что все мучения были излишними».
— Майк Моррисон, основатель Stalefish Labs
«Книга „Программируем для iPhone и iPad“ продолжает нарастающую тенденцию к изложе-нию сложных технических тем на доступном уровне, но без ущерба для глубины и мас-штабности материала. Программирование для iOS в любом случае придется покорять, как горную вершину, но с книгой „Программируем для iPhone и iPad“ вы будете взбираться на эту „гору“ по заранее проложенным маршрутам, со страховкой и в компании опытного проводника! Я рекомендую эту книгу каждому, кто хочет быстро освоить программирова-ние для этой непростой и интересной платформы».
— Крис Пилсор, snogboggin.com
ББК 32.973.2-018.1 УДК 004.434 Б41
Бенедетти Р., Крэнли Р. Б41 Изучаем работу с jQuery. — СПб.: Питер, 2012. — 528 с.: ил.
ISBN 978-5-459-00896-8
Хотите добавить интерактивности своему интернет-сайту? Узнайте, как jQuery позволит вам создать целый набор скриптов, используя всего несколько строчек кода! С помощью этого издания вы максимально быстро научитесь ра-ботать с jQuery — этой удивительной библиотекой JavaScript, использование которой сегодня стало необходимостью для разработки современных веб-сайтов и RIA-приложений. jQuery помогает легко получать доступ к любому эле-менту DOM, обращаться к атрибутам и содержимому элементов DOM, а также предоставляет богатые возможности по взаимодействию с AJAX. Особенностью данного издания является уникальный способ подачи материала, выделяющий серию «Head First» издательства O’Reilly в ряду множества скучных книг, посвященных программированию.
ББК 32.973.2-018.1 УДК 004.434
Права на издание получены по соглашению с O’Reilly. Все права защищены. Никакая часть данной книги не может быть воспроиз-ведена в какой бы то ни было форме без письменного разрешения владельцев авторских прав.
ISBN 978-1449393212 англ. © Authorized Russian translation of the English edition of titled Head First jQuery, 1st Edition (ISBN 9781449393212) © 2011, Ryan Benedetti and Ronan Cranley. This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to
publish and sell the same. ISBN 978-5-459-00896-8 © Перевод на русский язык ООО Издательство «Питер», 2012
© Издание на русском языке, оформление ООО Издательство «Питер», 2012
Мы посвящаем эту книгу магистрам JavaScript: Джону Рези-гу (создателю и ведущему разработчику библиотеки jQuery), Дугласу Крокфорду, Дэвиду Фленагану и Брэндону Эйку.
Моим трем феям: Джози, Вин и Шонне.
— Райан
Кейтлин и Боно: спасибо вам за все!
— Ронан
8
об авторах
Райан Бенедетти — обладатель степени ма-гистра искусств в области писательского ма-стерства (университет Монтаны); работает веб-разработчиком и специалистом по мульти-медиа в университете Портленда. В своей рабо-те использует jQuery, Flash, ActionScript, Adobe Creative Suite, Liferay Portal, Apache Jakarta Velocity и Drupal.
В течение семи лет Райан руководил факуль-тетом информационных и компьютерных технологий в колледже Салиш-Кутени. До этого он работал редактором и специалистом по информационным системам в программе исследования рек, ручьев и сильно увлажнен-ных земель в школе лесоводства при универ-ситете Монтаны.
Стихотворения Райана опубликованы в по-этических сборниках. В свободное время занимается рисованием, играет на губной гармошке и практикует сидячую медитацию. Свои лучшие моменты жизни Райан прово-дит с дочерью, сыном и своей любимой Шон-ной в Портленде, штат Орегон. Также любит выбираться на природу со своими четверо-ногими друзьями: Роки, Манчем, Фестером и Тазом.
Ронан Крэнли работал в университете Порт-ленда с момента своего переезда из Дубли-на, Ирландия, в 2006 году — с должности веб-разработчика до старшего веб-разработчика/инженера-системотехника и заместителя дирек-тора по веб-системам и администрированию.
Ронан получил степень бакалавра в области компьютерных технологий в технологиче-ском институте Дублина, который он закон-чил с отличием в 2003 году. Во время учебы, а также на своей предыдущей должности в ESB International (Дублин) и текущей в университе-те Портленда Ронан работал над разнообраз-ными проектами на языках PHP, VB.NET, C# и Java. Среди этих проектов была клиентская система GIS, система управления контентом, система календарного планирования и гибрид-ное приложение jQuery/Google Maps.
Помимо проектирования и построения веб-приложений, Ронан также занимается адми-нистрированием баз данных SQL Server. Сво-бодное время Ронан проводит на футбольном поле, на площадке для гольфа, а также со сво-ей женой Кейтлин и английским бульдогом Боно, наслаждаясь всей полнотой жизни на северо-западном Тихоокеанском побережье.
Райан
РонанРонан
9
содержание
Содержание (сводка)
Содержание (настоящее)
Ваш мозг думает о jQuery. Вы сидите за книгой и пытаетесь что-нибудь выучить, но ваш мозг считает, что вся эта писанина не нужна. Ваш мозг говорит: «Выгляни в окно! На свете есть более важные вещи, например сноуборд». Как заставить мозг думать, что ваша жизнь действительно зависит от jQuery?
Введение
Для кого написана эта книга? 24
Метапознание: наука о мышлении 27
Что можете сделать ВЫ, чтобы заставть свой мозгповиноваться 29
Примите к сведению 30
Технические рецензенты 34
Благодарности 35
Введение 23
1 Знакомство с jQuery. Живые веб-страницы 37
2 Селекторы и методы. Хватай и действуй 69
3 События и функции jQuery. Страница в центре событий 109
4 Операции со структурой страниц в jQuery. Изменение DOM 157
5 jQuery эффекты и анимация. Плавно и изящно 209
6 jQuery и JavaScript. Люк jQuery, я твой отец! 247
7 Пользовательские функции для пользовательских эффектов. Что будем делать? 285
8 jQuery и Ajax. Пожалуйста, передайте данные 321
9 Данные JSON. Клиент встречается с сервером 355
10 jQuery UI. Переработка форм 399
11 jQuery и APIs. Объекты, сплошные объекты 439
I Остатки. Десять важных вещей (которые мы не рассмотрели) 473
II Настройка среды разработки. Готовимся к великим свершениям 487
10
содержание
1 Живые веб-страницыВы хотите расширить возможности своих веб-страниц. Вы уже знаете HTML и CSS и хотите включить в свой арсенал сценарное программирование, но вам совершенно не хочется про-водить свою жизнь за написанием сотен строк кода. Нужна библио-тека сценариев, которая позволяла бы изменять веб-страницы «на ходу». И если на то пошло, как насчет поддержки AJAX и PHP? И чтобы в трех строках кода можно было сделать то, для чего в большинстве клиентских языков потребуется 15? Пустые мечты, скажете вы... А вот и нет! На помощь приходит jQuery.
Знакомство с jQuery
$( )
jQuery( )
$( )
Новые возможности веб-страниц 38
HTML и CSS — это, конечно, хорошо, но… 39…без сценариев не обойтись 40
Знакомьтесь: jQuery (и JavaScript)! 41
Что происходит в браузере 43
Скрытая структура веб-страницы 44
jQuery упрощает работу с DOM 45
Функция jQuery (и ее сокращенная запись) 48
jQuery выбирает элементы по тем же правилам,что и CSS 49
Селекторы: стили и сценарии 50
Использование селекторов jQuery 51
jQuery в переводе 52
Ваш первый проект с jQuery 56
Подготовка файлов HTML и CSS 60
Поехали… 62Эффекты изменения прозрачности 63
И это все? 64
Пушистые Друзья спасены 66
Ваш инструментарий jQuery 67Пользователь щелкнул мышью Эй, браузер, обнови для
меня этот элемент img!
11
содержание
2 Хватай и действуйjQuery помогает выбирать элементы веб-страниц и выпол-нять с ними всевозможные операции. В этой главе более подроб-но рассмотрены селекторы и методы jQuery. Селекторы jQuery выбирают элементы страницы, а методы выполняют операции с этими элементами. Библиотека jQuery, словно сборник магических заклинаний, позволяет изменять окружающую реальность. Вы можете заставить изображение исчезнуть или появиться из ниоткуда или же выбрать фрагмент текста и анимировать изменение его размера шрифта... Но довольно разгово-ров — хватайте элементы веб-страниц и действуйте!
Селекторы и методы
Подруга просит тебя помочь оформить сайт 70
Что требуется от проекта? 71
Начинаем с div 73
Событие click под увеличительным стеклом 76
Включение метода click в страницу 79
Выражайтесь точнее 81
Назначение классов 82
Идентификаторы элементов 83
Три уровня веб-страницы 86
Возвращаемся к списку 89
Выделение памяти для хранения данных 90
Конкатенация и слияние данных 91
Возвращаемся к программному коду… 92Вставка сообщения 93
Все отлично работает, но… 95Дайте мне $(this) 97
Использование $(this) 98
Скатертью дорога! Метод remove 100
Селекторы потомков 101
Ваша очередь прыгать от радости 107
Ваш инструментарий jQuery 108
12
содержание
Ни минуты покоя 110
В словах бухгалтера есть резон... 111
Реакция на события 113
За кулисами слушателя событий 114
Связывание события 115
Срабатывание событий 116
Удаление событий 120
Перебор элементов 124
Структура проекта 130
Использование функций 134
Как устроена функция 135
Анонимная функция 136
Именованные функции как обработчики событий 137
Передача переменных функциям 140
Функция также может возвращать значения 141
Условные конструкции и принятие решений 143
Но это еще не все 147
Методы могут изменять CSS 149
Добавление события hover 151
Еще немного... 153
Ваш инструментарий jQuery 156
3 Страница в центре событийjQuery позволяет легко включить в любую веб-страницу поддержку действий и интерактивности. В этой главе вы узнаете, как заставить вашу страницу реагировать на действия, выполняемые пользователем. Возможность выполнения кода в ответ на действия пользователя поднимает сайт на совершенно новый уровень. Также в этой главе рассказано, как создавать функ-ции, чтобы однократно написанный код можно было использовать много раз.
События и функции jQuery
Слушатель события, связанный с элементом, «слышит» событие click и сообщает интерпрета-тору JavaScript...
...Интерпретатор JavaScript
выполняет функцию, задан-
ную в слушателе события.
13
содержание
4 Изменение DOM
Операции со структурой страниц в jQuery
Завершение загрузки страницы еще не означает, что ее структура останется неизменной. В главе 1 было показано, как в процессе загрузки страницы строится модель DOM, опреде-ляющая ее структуру. В этой главе вы научитесь перемещаться по дереву DOM, работать с иерархией элементов и отношениями «родитель/потомок» для изменения структуры страницы «на ходу» средствами jQuery.
Интерактивное меню 158
Вегетарианцы, вперед! 159
Назначение классов элементам 164
Создание кнопок 167
Что дальше? 169
Перемещение по дереву DOM 174
Методы обхода дерева DOM 175
Сцепленные вызовы методов 176
В переменных также могут храниться элементы 183
И снова знак $... 184
Хранение данных в массивах 185
Хранение элементов в массиве 186
Изменение элементов методом replaceWith 188
Чем поможет replaceWith? 189
Не торопитесь с replaceWith 191
Когда replaceWith не подходит 192
Вставка HTML в DOM 193
Фильтры (часть 1) 195
Фильтры (часть 2) 196
Верните гамбургер на место 199
И где же мясо? 200
Массив отсоединенных элементов 201
Метод each и перебор массивов 202
Вроде… все? 205
Ваш инструментарий jQuery 208
Вашэлемент
14
содержание
5 Плавно и изящно
jQuery эффекты и анимация
Реализация всяких интересных возможностей — дело за-мечательное, но если ваша страница не будет хорошо смотреться, люди не станут приходить на сайт. И здесь на первый план выходят визуальные эффекты и анимация jQuery. Вы научитесь организовы-вать переходы, скрывать и отображать нужные части элементов, из-менять размеры элементов на странице — и все это на глазах у ваших посетителей! Вы научитесь планировать выполнение анимаций, что-бы они происходили с различными интервалами, отчего ваша страни-ца будет выглядеть исключительно динамично.
Новый заказ 210
Проект «Собери монстра» 211
Макет и позиционирование 212
Еще немного структуры и стиля 215
Проработка интерфейса 216
Эффект молнии 221
Как jQuery выполняет анимацию элементов? 222
Эффекты изменения прозрачности изменяютсвойство CSS opacity 223
Эффект скольжения 224
Как работают эффекты изменения прозрачности 226
Комбинированные эффекты 227
Задержка при использовании эффектов 228
Включение функций в сценарий 231
Самодельные эффекты и animate 233
Что можно анимировать? 234
Метод animate изменяет стилевое оформление 236
Откуда и куда? 239
Абсолютные и относительные перемещения элементов 240
Включение вызовов animate в сценарный код 243
Смотри, мама! Работает без Flash! 245
Ваш инструментарий jQuery 246
15
содержание
6 Люк jQuery, я твой отец!
jQuery и JavaScript
Силы jQuery небезграничны. Хотя эта библиотека написана на JavaScript, к сожалению, она позволяет сделать не все, на что способен язык-родитель. В этой главе мы рассмотрим некоторые возможности JavaScript, необходимые для создания современных сайтов, и их применение в jQuery для создания пользовательских списков и объектов, а также средства перебора списков и объектов, которые существенно упростят вашу работу.
1 2 3 4 2 3 4... ... ... ... ... ... ...
Программируем блэкджек 248
Объекты и хранение данных 250
Построение собственных объектов 251
Создание объектов для повторного использования 252
Взаимодействие с объектами 253
Подготовка страницы 254
И снова массивы 257
Обращение к ячейкам массива 258
Добавление и обновление ячеек 259
Повторение операций 261
Поиск иголки в стоге сена 264
Пора принимать решение... снова! 271
Операторы сравнения и логические операторы 272
Стирание информации в jQuery 278
Чтобы было красивее 282
Ваш инструментарий jQuery и JavaScript 284
16
содержание
7 Что будем делать?
Пользовательские функции для пользовательских эффектов
От объединения пользовательских эффектов jQuery с функ-циями JavaScript ваш код (и ваши веб-приложения) ста-новится более эффективным и более мощным. В этой главе мы займемся совершенствованием эффектов jQuery посредством обработки событий браузера, использования временных функций и улучшения общей структуры и возможностей повторного использова-ния пользовательских функций JavaScript.
Надвигается буря 286
Мы создали монстра... функцию-монстра 287
Управление временными эффектами 288
Обработка событий браузера в onblur и onfocus 291
Методы работы с таймером определяют времявыполнения функций 295
Пишем функции stopLightning и goLightning 298
Новая просьба 306
Случайные монстры 307
Мы уже знаем текущую позицию... 308
...и функция getRandom уже готова 308
Перемещение относительно текущей позиции 312
«Собери монстра-2» — настоящий хит! 319
Ваш инструментарий jQuery 320
Конечно, зубы — главное,что есть у монстра,
но остаться без лицакак-то не хочется!
17
содержание
8 Пожалуйста, передайте данные
jQuery и Ajax
Использовать jQuery для всяких фокусов с CSS и DOM до-вольно весело, но при программировании веб-приложений необходимо получать данные с сервера и отображать их на странице. Возможно, вам даже захочется обновлять небольшие фрагменты страницы без полной перезагрузки страницы. Технология Ajax в сочетании с jQuery и JavaScript позволяет решить эту задачу. В этой главе вы узнаете, как в jQuery реа-лизуются обращения Ajax к серверу и что можно сделать с полученной информацией.
li
$(“li”).find(“ul”)
Ежегодные Ежегодные соревнованиясоревнования
В этом году марафон проходит на Мауи,
заказывайте билеты заблаговременно!
Бегом к современным технологиям 322
Прошлогодняя страница 323
Даешь динамику! 326
СТАРЫЕ и НОВЫЕ веб-технологии 327
Структура Ajax 328
Что такое Ajax? 328
Фактор «X» 329
Получение данных методом ajax 334
Разбор данных XML 336
Планирование событий 340
Самоактивизируемые функции 341
Сервер нам поможет 344
Который час? 345
Отключение планирования событий на странице 350
Ваш инструментарий jQuery/Ajax 354
18
содержание
9 Клиент встречается с сервером
Данные JSON
Возможность чтения данных из файлов XML безусловно по-лезна, но иногда этого оказывается недостаточно. Другой, более эффективный формат передачи данных JSON (JavaScript Object Notation) упрощает получение данных со стороны сервера. Кроме того, данные JSON проще генерируются и читаются, чем данные XML. При помощи jQuery, PHP и SQL можно создать базу данных для хранения информации, которая позднее читается с использованием JSON и отображается на экра-не средствами jQuery. Вот она, истинная мощь веб-приложений!
В отделе маркетинга MegaCorp никто не знает XML 356
Ошибки в XML 357
Ввод данных на веб-странице 358
Что делать с данными 361
Форматирование данных перед отправкой 362
Отправка данных серверу 363
Хранение информации в базе данных MySQL 365
Создание базы данных для информации об участниках 366
Строение команды insert 368
Использование PHP для работы с данными 371
Обработка данных POST на сервере 372
Подключение к базе данных из кода PHP 373
Чтение из базы данных 375
Доступ к данным в коде PHP 377
На помощь приходит JSON! 380
jQuery + JSON = потрясающе 381
Несколько правил PHP... 382
Правила PHP (еще немного)... 383
Форматирование вывода средствами PHP 384
Работа с данными в объекте JSON 391
Проверка и чистка данных в PHP 394
Ваш инструментарий jQuery/Ajax/PHP/MySQL 397
19
содержание
Переработка форм
jQuery UI
10 Пользователи и их данные — жизнь и смерть веб-приложений. Ввод данных пользователем — серьезная задача, которая может отнять много времени у веб-разработчика. Вы уже видели, как jQuery упрощает построение веб-приложений, использующих Ajax, PHP и MySQL. Теперь давайте посмотрим, как jQuery упрощает построение пользовательского интерфейса форм для ввода данных пользователем. Заодно вы узнаете много полезного о jQuery UI — официальной библиотеке пользователь-ского интерфейса для jQuery.
??
Cryptozoologists.org нуждается в переработке 400
Новая форма HTML 401
jQuery UI экономит время и силы 404
Содержимое пакета jQuery UI 408
Построение календаря 409
Незаметное вмешательство jQuery UI 410
Изменение параметров виджета 411
Стильные кнопки 414
Ограничение ввода числовых данных 418
Создание цвета по трем составляющим 427
Функция refreshSwatch 430
И последнее... 434
Ваш инструментарий jQuery 438
Тоже мне, удружили!Теперь не будетни минуты покоя!
20
содержание
Объекты, сплошные объекты
jQuery и APIs
11 Даже самый талантливый разработчик не сможет сделать всю работу в одиночку... Мы уже видели, как включать расширения jQuery (такие как jQuery UI или вкладки) для повышения уровня функцио-нальности приложения. Чтобы поднять наше приложение на следующий уровень — использовать Интернет и информацию из крупных информа-ционных систем типа Google, Twitter или Yahoo! — понадобится... нечто большее. Эти компании предоставляют вам программные интерфейсы (API, Application Programming Interface). В этой главе мы рассмотрим ос-новы работы с API, а также используем очень распространенный сервис Google Maps API.
Привет! Я маркер. Раз познакомиться. Мы ведь уже встречались на картах
Google, не так ли?
Где видели снежного человека? 440
Google Maps API 442
В API используются объекты 443
Включение карт Google в страницу 445
Чтение данных JSON средствами SQL и PHP 448
Точки на карте — маркеры 452
Список задач для отображения нескольких существ 456
Прослушивание событий карты 466
Получилось!!! 470
Ваш инструментарий jQuery API 471
Пара слов на прощание… 472
21
содержание
I Десять важных вещей(которые мы не рассмотрели)Даже после всего сказанного многое осталось «за кадром». Существует масса других полезных возможностей jQuery и JavaScript, которые нам не удалось вместить в книгу. Было бы неправильно даже не упомянуть о них. Мы хотим, чтобы вы были готовы к любому аспек-ту jQuery, с которым вы можете столкнуться во время самостоятель-ных исследований.
Остатки
1. Все, что есть в библиотеке jQuery 474
2. jQuery CDN 477
3. Пространство имен jQuery: метод noConflict 478
4. Отладка кода jQuery 479
5. Расширенная анимация и очереди 480
6. Проверка форм 481
7. Эффекты jQuery UI 482
8. Создание собственных модулей расширения jQuery 483
9. Замыкания 484
10. Шаблоны 485
содержание
II Готовимся к великим свершениямВам понадобится среда, в которой вы сможете потренировать свои навыки PHP, но так, чтобы ваши данные не стали уязви-мыми для внешних атак. Разработку приложений PHP всегда жела-тельно начинать с безопасной среды и только потом открывать доступ для внешнего мира. В этом приложении приведены инструкции по установке веб-сервера, MySQL и PHP. После их выполнения в вашем распоряжении появится безопасная среда для работы и экспериментов.
Настройка среды разработки
Создание среды разработки PHP 488
Что у вас уже есть? 488
У вас установлен веб-сервер? 489
У вас установлена поддержка PHP? Какая версия? 489
У вас установлен MySQL? Какая версия? 490
Начнем с веб-сервера 491
Установка Apache... завершение 492
Установка PHP 492
Действия по установке PHP 493
Действия по установке PHP... завершение 494
Установка MySQL 494
Установка MySQL в системе Windows 495
Включение поддержки PHP в Mac OS X 500
Установка MySQL в Mac OS X 500
Как пользоваться этой книгой
ВведениеНе могу поверить, что они включили такое
в книгу о jQuery!
В этом разделе мы ответим на насущный вопрос:
«Так почему они включили ТАКОЕ в книгу о jQuery?»
Вам нравится?Книга стоит денег, которые вы заплатили за нее, и станет лучшим подарком.
24 введение
как пользоваться этой книгой
1
2
3
Äëÿ êîãî íàïèñàíà ýòà êíèãà?
Êîìó ýòà êíèãà íå ïîäîéäåò?
Если вы ответите «да» на все следующие вопросы:
Если вы ответите «да» на любой из следующих вопросов:
...то эта книга для вас.
...эта книга не для вас.
[Заметка от отдела продаж: вообще-то эта книга для любого, у кого есть деньги.]
У вас уже имеется опыт веб-разработки или веб-дизайна?
Вы хотите изучить, запомнить, понять и научиться применять важнейшие концепции jQuery и JavaScript, чтобы сделать ваши страницы более интерактивными и интересными?
Вы предпочитаете оживленную беседу сухим, скуч-ным академическим лекциям?
1
2
3
Вы абсолютно не разбираетесь в веб-программировании?
Вы уже занимаетесь разработкой веб-приложений, и ищете справочник по jQuery?
Вы боитесь попробовать что-нибудь новое? Скорее пойдете к зубному врачу, чем наденете по-лосатое с клетчатым? Считаете, что техническая книга со снежным человеком серьезной быть не может?
Безусловно, навыки сце-нарного программирования тоже пригодятся. Опыт использования JavaScript полезен, но необязателен.
Обратитесь к книге «Изучаем HTML, XHTML и CSS» (Питер, 2012) — в ней приведен отличный вводный курс веб-программирования. А потом воз-вращайтесь к нам!
дальше� 25
введение
Замечательно. Еще 487 сухих,
скучных страниц.
Ìû çíàåì, î ÷åì âû äóìàåòå
È ìû çíàåì, î ÷åì äóìàåò âàø ìîçã
«Разве серьезные книги по программированию такие?»
«И почему здесь столько рисунков?»
«Можно ли так чему-нибудь научиться?»
Мозг жаждет новых впечатлений. Он постоянно ищет, ана-лизирует, ожидает чего-то необычного. Он так устроен, и это помогает нам выжить.
Как наш мозг поступает со всеми обычными, повседневны-ми вещами? Он всеми силами пытается оградиться от них, чтобы они не мешали его настоящей работе — сохранению того, что действительно важно. Мозг не считает нужным сохранять скучную информацию. Она не проходит фильтр, отсекающий «очевидно несущественное».
Но как же мозг узнает, что важно? Представьте, что вы вы-ехали на прогулку и вдруг прямо перед вами появляется тигр. Что происходит в вашей голове и теле?
Активизируются нейроны. Вспыхивают эмоции. Происходят химические реакции. И тогда ваш мозг понимает...
Конечно, это важно! Не забывать!А теперь представьте, что вы находитесь дома или в библио-теке, в теплом, уютном месте, где тигры не водятся. Вы учи-тесь — готовитесь к экзамену. Или пытаетесь освоить слож-ную техническую тему, на которую вам выделили неделю... максимум десять дней.
И тут возникает проблема: ваш мозг пытается оказать вам услугу. Он старается сделать так, чтобы на эту очевид-но несущественную информацию не тратились драгоцен-ные ресурсы. Их лучше потратить на что-нибудь важное. На тигров, например. Или на то, что к огню лучше не при-касаться. Или что на лыжах не стоит кататься в футболке и шортах.
Нет простого способа сказать своему мозгу: «Послушай, мозг, я тебе, конечно, благодарен, но какой бы скучной ни была эта книга и пусть мой датчик эмоций сейчас на нуле, я хочу запомнить то, что здесь написано».
Ваш мозг считает, что ЭТО важно.
Ваш мозг пола-
гает, что ЭТО
можно не запо-
минать.
26 введение
как пользоваться этой книгойкак пользоваться этой я книгой
Как мы что-то узнаем? Сначала нужно это «что-то» понять, а потом не забыть. Затол-
кать в голову побольше фактов недостаточно. Согласно новейшим исследованиям в об-
ласти когнитивистики, нейробиологии и психологии обучения, для усвоения матери-
ала требуется что-то большее, чем простой текст на странице. Мы знаем, как заставить
ваш мозг работать.
Основные принципы серии Head First:
Наглядность. Графика запоминается гораздо луч-
ше, чем обычный текст, и значительно повышает
эффективность восприятия информации (до
89 % по данным исследований). Кроме того,
материал становится более понятным. Текст
размещается на рисунках, к которым он отно-
сится, а не под ними или на соседней странице.
Разговорный стиль изложения. Недавние исследо-
вания показали, что при разговорном стиле изложения матери-
ала (вместо формальных лекций) улучшение результатов на
итоговом тестировании достигает 40 %. Рассказывайте историю, вместо того чтобы
читать лекцию. Не относитесь к себе слишком серьезно. Что привлечет ваше внимание:
занимательная беседа за столом или лекция?
Активное участие читателя. Пока вы не начнете напрягать извилины, в вашей
голове ничего не произойдет. Читатель должен быть заинтересован в результате; он
должен решать задачи, формулировать выводы и овладевать новыми знаниями. А для
этого необходимы упражнения и каверзные вопросы, в решении которых задействова-
ны оба полушария мозга и разные чувства.
Привлечение (и сохранение) внимания читателя.
Ситуация, знакомая каждому: «Я очень хочу изучить это, но за-
сыпаю на первой странице». Мозг обращает внимание на интересное, странное,
притягательное, неожиданное. Изучение сложной технической темы не обязано
быть скучным. Интересное узнается намного быстрее.
Обращение к эмоциям. Известно, что наша способность запоминать
в значительной мере зависит от эмоционального сопереживания. Мы запо-
минаем то, что нам небезразлично. Мы запоминаем, когда что-то чувствуем.
Нет, сентименты здесь ни при чем: речь идет о таких эмоциях, как удивление,
любопытство, интерес, и чувстве «Да я крут!» при решении задачи, которую
окружающие считают сложной, — или когда вы понимаете, что разбираетесь
в теме лучше, чем всезнайка-Боб из технического отдела.
Эта книга для тех, кто хочет учиться.
$( )
jQuery( )
$( ) Вы можете замедлить дви-
жение и заставить картинку
исчезнуть?
ПриСитусыпаприбыт
Обв мНл
Ежегодные Ежегодные
соревнованиясоревнования
В этом году марафон
проходит на Мауи,
заказывайте билеты
заблаговременно!
дальше� 27
введение
Если вы действительно хотите быстрее и глубже усваивать новые зна-ния — задумайтесь над тем, как вы задумываетесь. Учитесь учиться.
Мало кто из нас изучает теорию метапознания во время учебы. Нам положено учиться, но нас редко этому учат.
Но раз вы читаете эту книгу, то, вероятно, вы хотите освоить jQuery, и по возможности быстрее. Вы хотите запомнить прочи-танное, а для этого абсолютно необходимо сначала понять про-читанное.
Чтобы извлечь максимум пользы из учебного процесса, нужно заставить ваш мозг воспринимать новый материал как Нечто Важное. Критичное для вашего существования. Такое же важ-ное, как тигр. Иначе вам предстоит бесконечная борьба с вашим мозгом, который всеми силами уклоняется от запоминания но-вой информации.
Ìåòàïîçíàíèå: íàóêà î ìûøëåíèè
Как бы теперь заставить мой мозг все это запомнить...
Как же УБЕДИТЬ мозг, что программирование для jQuery не менее важно, чем тигр?Есть способ медленный и скучный, а есть быстрый и эффек-тивный. Первый основан на тупом повторении. Всем известно, что даже самую скучную информацию можно запомнить, если повторять ее снова и снова. При достаточном количестве повторений ваш мозг прикиды-вает: «Вроде бы несущественно, но раз одно и то же повторяется столько раз... Ладно, уговорил».
Быстрый способ основан на повышении активности мозга и особенно со-четании разных ее видов. Доказано, что все факторы, перечисленные на пре-дыдущей странице, помогают вашему мозгу работать на вас. Например, ис-следования показали, что размещение слов внутри рисунков (а не в подписях, в основном тексте и т. д.) заставляет мозг анализировать связи между текстом и графикой, а это приводит к активизации большего количества нейронов. Больше нейронов — выше вероятность того, что информация будет сочтена важной и достойной запоминания.
Разговорный стиль тоже важен: обычно люди проявляют больше внимания, когда они участвуют в разговоре, так как им приходится следить за ходом бе-седы и высказывать свое мнение. Причем мозг совершенно не интересует, что вы «разговариваете» с книгой! С другой стороны, если текст сух и фор-мален, то мозг чувствует то же, что чувствуете вы на скучной лекции в роли пассивного участника. Его клонит в сон.
Но рисунки и разговорный стиль — это только начало.
28 введение
как пользоваться этой книгой
Âîò ÷òî ñäåëàëè ÌÛ:Мы использовали рисунки, потому что мозг лучше приспособлен для воспри-ятия графики, чем текста. С точки зрения мозга рисунок действительно стоит тысячи слов. А когда текст комбинируется с графикой, мы внедряем текст пря-мо в рисунки, потому что мозг при этом работает эффективнее.
Мы используем избыточность: повторяем одно и то же несколько раз, приме-няя разные средства передачи информации, обращаемся к разным чувствам — и все для повышения вероятности того, что материал будет закодирован в не-скольких областях вашего мозга.
Мы используем концепции и рисунки несколько неожиданным образом, по-тому что мозг лучше воспринимает новую информацию. Кроме того, рисунки и идеи обычно имеют эмоциональное содержание, потому что мозг обращает вни-мание на биохимию эмоций. То, что заставляет нас чувствовать, лучше запоми-нается — будь то шутка, удивление или интерес.
Мы используем разговорный стиль, потому что мозг лучше воспринимает ин-формацию, когда вы участвуете в разговоре, а не пассивно слушаете лекцию. Это происходит и при чтении.
В книгу включены многочисленные упражнения, потому что мозг лучше запо-минает, когда вы что-то делаете. Мы постарались сделать их непростыми, но интересными — то, что предпочитает большинство читателей.
Мы совместили несколько стилей обучения, потому что одни читатели предпо-читают пошаговые описания, другие стремятся сначала представить «общую картину», а третьим хватает фрагмента кода. Независимо от ваших личных предпочтений полезно видеть несколько вариантов представления одного ма-териала.
Мы постарались задействовать оба полушария вашего мозга; это повышает веро-ятность усвоения материала. Пока одна сторона мозга работает, другая часто имеет возможность отдохнуть; это повышает эффективность обучения в тече-ние продолжительного времени.
А еще в книгу включены истории и упражнения, отражающие другие точки зрения. Мозг глубже усваивает информацию, когда ему приходится оценивать и выносить суждения.
В книге часто встречаются вопросы, на которые не всегда можно дать простой ответ, потому что мозг быстрее учится и запоминает, когда ему приходится что-то делать. Невозможно накачать мышцы, наблюдая за тем, как занимаются другие. Однако мы позаботились о том, чтобы усилия читателей были приложе-ны в верном направлении. Вам не придется ломать голову над невразумитель-ными примерами или разбираться в сложном, перенасыщенном техническим жаргоном или слишком лаконичном тексте.
В историях, примерах, на картинках используются люди — потому что вы тоже человек. И ваш мозг обращает на людей больше внимания, чем на неодушевлен-ные предметы.
Беседа у камина
Тест-драйв
дальше� 29
введение
Мы свое дело сделали. Остальное за вами. Эти советы станут отправной точкой; прислушайтесь к своему мозгу и опреде-лите, что вам подходит, а что не подходит. Пробуйте новое.
1
2
3
4
5 Пейте воду. И побольше.Мозг лучше всего работает в условиях высо-кой влажности. Дегидратация (которая может наступить еще до того, как вы почувствуете жажду) снижает когнитивные функции.
Не читайте другие книги после этойперед сном.
6
7
9 Творите!Попробуйте применить новые знания в своей повседневной работе. Просто сделайте хоть что-нибудь, чтобы приобрести практический опыт за рамками упражнений. Все, что для этого нужно — это карандаш и подходящая задача... задача, в которой изучаемые методы и инструменты могут принести пользу.
Прислушивайтесь к своему мозгу.
8 Чувствуйте!Ваш мозг должен знать, что материал книги действительно важен. Переживайте за героев наших историй. Придумывайте собственные подписи к фотографиям. Поморщиться над неудачной шуткой все равно лучше, чем не по-чувствовать ничего.
Следите за тем, когда ваш мозг начинает уста-вать. Если вы начинаете поверхностно вос-принимать материал или забываете только что прочитанное — пора сделать перерыв. С определенного момента попытки «затол-кать» в мозг дополнительную информацию не только не ускоряют обучение, а скорее идут во вред ему.
Говорите вслух.Речь активизирует другие участки мозга. Если вы пытаетесь что-то понять или получше за-помнить, произнесите вслух. А еще лучше, попробуйте объяснить кому-нибудь другому. Вы будете быстрее усваивать материал и, воз-можно, откроете для себя что-то новое.
Часть обучения (особенно перенос информа-ции в долгосрочную память) происходит по-сле того, как вы откладываете книгу. Ваш мозг не сразу усваивает информацию. Если во вре-мя обработки поступит новая информация, часть того, что вы узнали ранее, может быть потеряна.
Читайте врезки.Это значит: читайте все. Врезки — часть основно-го материала! Не пропускайте их.
Выполняйте упражнения, делайте заметки.Мы включили упражнения в книгу, но выпол-нять их за вас не собираемся. И не разглядывай-те упражнения. Берите карандаш и пишите. Физические действия во время учения повыша-ют его эффективность.
Не торопитесь. Чем больше вы поймете,тем меньше придется запоминать.Просто читать недостаточно. Когда книга задает вам вопрос, не переходите к ответу. Представьте, что кто-то действительно задает вам вопрос. Чем глубже ваш мозг будет мыс-лить, тем скорее вы поймете и запомните ма-териал.
Вырежьте и прикрепите на холодильник.
×òî ìîæåòå ñäåëàòü ÂÛ, ÷òîáû
çàñòàâèòü ñâîé ìîçã ïîâèíîâàòüñÿ
30 введение
как пользоваться этой книгой
Ïðèìèòå ê ñâåäåíèþ
Это учебник, а не справочник. Мы намеренно убрали из книги все, что могло бы помешать изучению материала, над которым вы работаете. И при первом чтении книги начинать следу-ет с самого начала, потому что книга предполагает наличие у читателя определенных знаний и опыта.
Предполагается, что вы уже знаете HTML и CSS.
Если вы еще не знаете HTML и CSS, то для начала найдите книгу Head First HTML with CSS & XHTML. В этой книге мы напомним вам, как работают селекторы CSS, но не ждите, что здесь будет рассказано все, что необходимо знать о CSS.
От вас не требуется знание JavaScript.
Знаем, знаем — кто-то с нами не согласится, но мы считаем, что jQuery можно изучать без пред-варительного изучения JavaScript. Конечно, для написания кода jQuery необходимо знать не-которые концепции JavaScript, но мы представим их одновременно с описанием кода jQuery. Мы глубоко и искренне верим в девиз jQuery: Меньше Кода, Больше Дела.
Мы рекомендуем использовать разные браузеры.
Страницы желательно тестировать по крайней мере в трех современных браузерах. Так вы уз-наете, чем отличаются разные браузеры, и научитесь создавать страницы, нормально работаю-щие в разных браузерах.
Эта книга не о браузерных средствах разработчика…
...но предполагается, что вы умеете пользоваться ими. Мы настоятельно рекомендуем исполь-зовать браузер Google Chrome, который можно загрузить по адресу http://www.google.com/chrome. Информация о браузерах и их средствах разработчика представлена на следующих сайтах:
Google Chrome http://code.google.com/chrome/devtools/docs/overview.html
Firefox Firebug http://getfirebug.com/wiki/index.php/FAQ
Safari http://www.apple.com/safari/features.html#developer
Internet Explorer 8 http://msdn.microsoft.com/en-us/library/dd565628(v=vs.85).aspx
Internet Explorer 9 http://msdn.microsoft.com/en-us/ie/aa740478
Opera Dragonfly http://www.opera.com/dragonfly/
Мы надеемся, что вы не ограничитесь чтением книги.
Лучшее, что можно сделать при изучении чего-то нового — присоединиться к сообществу изучаю-щих. Мы считаем, что сообщество jQuery — одно из лучших, самых активных сообществ в мире со-временных технологий. Дополнительная информация приводится на сайте http://www.jquery.com.
дальше� 31
введение
Упражнения ОБЯЗАТЕЛЬНЫ.
Упражнения являются частью основного материала книги. Одни упражнения спо-собствуют запоминанию материала, другие помогают лучше понять его, третьи ори-ентированы на его практическое применение. Не пропускайте упражнения.
Повторение применяется намеренно.
У книг этой серии есть одна принципиальная особенность: мы хотим, чтобы вы действительно хорошо усвоили материал. И чтобы вы запомнили все, что узнали. Большинство справочников не ставит своей целью успешное запоминание, но это не справочник, а учебник, поэтому некоторые концепции излагаются в книге по не-скольку раз.
Упражнения «Мозговой штурм» не имеют ответов.
В некоторых из них правильного ответа вообще нет, в других вы должны сами ре-шить, насколько правильны ваши ответы (это является частью процесса обучения). В некоторых упражнениях «Мозговой штурм» приводятся подсказки, которые по-могут вам найти нужное направление.
Òðåáîâàíèÿ ê ïðîãðàììíîìó îáåñïå÷åíèþ
Для написания кода jQuery вам понадобится текстовый редактор, браузер, веб-сервер (он может работать локально на вашем персональном настольном компьюте-ре) и библиотека jQuery.
В системе Windows мы рекомендуем использовать редакторы PSPad, TextPad и EditPlus (хотя при желании можно работать и в Блокноте). Для Mac можно вос-пользоваться редактором TextWrangler. В системе Linux имеется много встроенных текстовых редакторов; вероятно, пользователям этой системы не нужно рассказы-вать про них.
Для разработки веб-приложений понадобится веб-сервер. Для последних глав книги (9, 10 и 11) вам стоит обратиться к приложению с описанием установки PHP, MySQL и веб-сервера (Apache или IIS) и выполнить приведенные там инструкции. Сделайте это прямо сейчас. Нет, серьезно — откройте приложение, выполните инструкции и возвращайтесь, когда все необходимое будет установлено.
Вам также понадобится браузер и средства разработчика (см. предыдущую страни-цу). Научитесь пользоваться консолью JavaScript в Google Chrome Dev Tools — вы не пожалеете о потраченном времени. Считайте, что это домашнее задание, которое вы должны выполнить самостоятельно.
Наконец, вам понадобится сама библиотека jQuery; о том, где ее взять, рассказано на следующей странице.
32 введение
как пользоваться этой книгой
Çàãðóçêà jQuery
Пора браться за дело. Откройте сайт jQuery и загрузите ко-пию библиотеки, которую вы будете использовать в книге.
Шаг 1:
Шаг 2:
Запустите браузер и введите в нем адрес http://www.jquery.com.
Шаг 3:
Найдите раздел «Grab the Latest Version» и установите флажок рядом со строкой «Production».
Шаг 4:
Щелкните на кнопке «Download jQuery».
Открывается следующая страница, которая выглядит примерно так.
Сохраните ее в папке с именем scripts.
scripts
jquery-1.6.2.min.js
Рабочая версия оптимизирована для максимальной скорости выпол-нения на веб-сервере. Версия для разработчика предназначена для изучения внутреннего строения библиотеки jQuery. Если вы любите «покопаться во внутренностях» библиотек, загрузите обе версии.
Чем рабочая (Production) версия отличается от версии для разработчика (Development)?
дальше� 33
введение
Ñòðóêòóðà ïàïîê
В папке каждой главы присутствует пап-ка begin, в которой хранится начальный вариант кода этой главы.
После загрузки и распаковки кода с сайта Head First Labs (http://www.headfirstlabs.com/books/hfjquery) вы увидите, что для каждой главы книги в структуре кода создана отдельная папка. Для примера возь-мем папку ch03:
Папка end в папке каждой главы содержит итоговую версию кода этой главы. Используйте папку end только для того, чтобы сверить ее с вашей версией кода.
В папке styles находится файл my_style.css, в кото-ром хранится начальная версия стилей для этой главы.
В папке scripts находится
только что загруженная
вами библиотека jQuery.
Вы можете свободно использовать библиотеку jQuery в любых сво-их проектах. Для удобства мы включили jQuery в папки с кодом кни-ги, однако вы должны знать, где загрузить jQuery для ваших будущих проектов, а также при выходе новой версии — библиотека jQuery регулярно обновляется.
Файл my_scripts.js содержит
код, который вы напишете
в этой книге. Постарайтесь
не заглядывать в него без
крайней необходимости.
Файл index.htmlсодержит размет-ку веб-приложений.
34 введение
Íàó÷íûå ðåäàêòîðû
группа рецензирования
Пол БарриЛиндси Скурас
Джим Доран работает программистом в университете Джона Хопкинса в Балтиморе, штат Мэриленд. Он преподает JavaScript в муниципальном колледже округа Балтимор, а также выступает с лекциями о jQuery на веб-конференциях. В остальное время Джим ведет блог по адресу http://jimdoran.net и катается на роликовых коньках.
Билл Мителски был научным редактором нескольких книг из серии Head First. В настоящее время он работает программистом в крупном национальном медицинском центре в окрестностях Чикаго, где занимается биостатистическими исследованиями. Когда он не занят сбором и обработкой данных, его можно найти на поле для гольфа, где он гоняет маленький белый мячик.
Линдси Скурас — юрист из Вашингтона. Она самостоятельно научилась программировать в свободное время по книгам серии Head First. Ее другие увлечения — чтение, рукоделие, посещение музеев и про-ведение свободного времени с мужем и собаками.
Пол Барри читает лекции по компьютерным дисциплинам в технологическом институте Карлоу (Ир-ландия). Пол пишет для журнала Linux Journal, а также опубликовал несколько технических книг. Он является автором Head First Python и соавтором Head First Programming. В свободное время Пол консуль-тирует малые и средние предприятия, а также начинающие фирмы по ведению программных проектов.
Билл Мителски
Джим Доран
дальше� 35
введение
Áëàãîäàðíîñòè
Кортни НэшККортни Н
Лу Барр
Группе O’Reilly:
Спасибо Лу Барр за быструю, превосходную и просто волшебную работу. Благода-ря ей эта книга приняла свою окончательную форму и стала такой красивой.
Спасибо Лори Петрики за то, что она дала «зеленый свет» нашему проекту. Рай-ан сохранил теплые воспоминания о программе обучения авторов HF в Бостоне и никогда не забудет классной, семейной атмосферы, которую здесь создала Лори.
Спасибо Карен Шанер. Спасибо всем специалистам из группы технического ре-цензирования.
Райан никогда не забудет тот день, когда он обнаружил первую книгу серии Head First в книжном магазине. Спасибо Кэти Сьерра и Берту Бэйтсу за то, что они по-могли расшевелить нейроны умников по всему миру. Спасибо Берту за то, что он слушал наши жалобы, помогал избавиться от нашей ограниченности и сохранять объективный взгляд на мир ; )
Спасибо Тиму О’Рейли за лучшее издательство технической литературы!
Друзьям и семье Ронана:
Я особенно благодарен своей жене Кейтлин — ее фантастические способности к дизайну и знание всех тонкостей Adobe позволили этой книге воплотиться в жизни. А еще спасибо за ее терпение — без тебя у меня бы ничего не получилось! Огромное спасибо всем, кто поддерживал нас в этой работе: моим соседям, моим коллегам по университету Портленда, моей футбольной команде и товарищам по гольфу. Спасибо моей ирландской семье за под-держку и помощь. И самое главное — спасибо Райану Бенедетти, моему замечательному со-автору, коллеге и другу. Спасибо, что вывел меня в этот путь. Это было незабываемо!
Нашему редактору:
Спасибо (и наши поздравления!) Кортни Нэш, которая заставила нас выложиться «на полную» в работе над книгой. Она справи-лась с огромным потоком сообщений, вопросов, жалоб и наших капризов. Она постоянно была рядом с нами и доверяла нам — а мы, естественно, доверяли ей.
Друзьям и семье Райана:
Спасибо моей дочери Джози, моему сыну Винни и моей невесте Шонне — они верили в меня и ежедневно поддерживали в работе над книгой. Ti amo, i miei tre miracoli. Я люблю вас всех, вы мои три чуда!
Спасибо маме и папе; моему брату Джеффу; моим племянницам Клэр и Квинн. Спасибо моим коллегам и группе WAS из университета Портленда — а именно Дженни Уолш, Джейкобу Кани-пароли и «вторниковой» технической группе (сами знаете, о ком я). Спасибо Кейтлин Пирс-Крэнли за ее выдающиеся навыки дизайна. Спасибо моему приятелю «ирландскому ниндзя» (также известному как Ронан Крэнли) за его мастерство программирования jQuery, JavaScript и PHP; его чувство юмора и невероятную трудовую дисциплину в работе над книгой.
Может, здесь найдется что-нибудь для улучшения
интерактивности моихвеб-страниц...
Знакомство с jQuery1
Живые веб-страницы
Вы хотите расширить возможности своих веб-страниц. Вы уже знаете HTML и CSS и хотите включить в свой арсенал сценарное програм-мирование, но вам совершенно не хочется проводить свою жизнь за написа-нием сотен строк кода. Нужна библиотека сценариев, которая позволяла бы изменять веб-страницы «на ходу». И если на то пошло, как насчет поддержки AJAX и PHP? И чтобы в трех строках кода можно было сделать то, для чего в большинстве клиентских языков потребуется 15? Пустые мечты, скажете вы... А вот и нет! На помощь приходит jQuery.
38 глава 1
страницы в движении
Íîâûå âîçìîæíîñòè âåá-ñòðàíèö
Вы уже умеете строить замечательные веб-страницы из чистого, синтаксически правильного кода HTML и CSS. Но статические веб-страницы сегодня никому не нужны — пользователи требуют динамики, анимации, интерактивности и современных эффектов.
Клиентам нравится дизайн моих веб-страниц, но они
требуют большей интерактив-ности. У нашей компании такой скучный сайт... Мы
не будем пользоваться им, пока он не станет более динамичным.
Хотите управлять своими веб-страницами и сделать их более удобными
для посетителей? Отметьте все нужные пункты в следующем списке.
Динамическое включение элементов в веб-страницу без ее полной перезагрузки.
Изменение элементов меню при наведении на них указателя мыши.
Оповещение пользователя о незаполненных полях формы.
Поддержка движения и переходов в тексте и графике.
Загрузка данных с сервера в тот момент, когда они понадобятся пользователю.
Возьми в руку карандаш
дальше � 39
знакомство с jquery
Когда пользователь вводит веб-адрес в адресной строке, браузер запрашива-ет веб-страницу у сервера.
1
Сервер находит запрашива-емый файл (или файлы) и отправляет его браузеру.
2
Браузер отображает страницу HTML на основа-нии файла, полученного от сервера.
3
HTML è CSS — ýòî, êîíå÷íî, õîðîøî, íî…
index.htmlБраузер загружает страницу и отображает ее для пользователя.
Старые добрые технологии HTML и CSS определяют структуру и стилевое оформ-ление веб-страницы. Готовая страница прекрасно отображается в браузере, но она остается статической.
А если понадобится изменить ее внешний вид, что-то добавить или удалить? При-ходится либо идти на немыслимые выкрутасы с CSS, либо просто загружать новую страницу. Оба варианта оставляют желать лучшего. Почему? Да потому что HTML и CSS предназначены для управления внешним видом страницы.
Веб-сервер
Мне, пожалуйста, файл index.html.
Вот, держи.
index.html
40 глава 1
действуй по сценарию
…áåç ñöåíàðèåâ íå îáîéòèñü
Чтобы изменять веб-страницы «на ходу», без полной переза-грузки, необходимо отдать соответствующую команду браузе-ру. Как это сделать? При помощи тега HTML < script>.
index.html
<script>
Тег <script> сообщает брау-зеру, что он должен выпол-нить некоторые действия.
Тег <script> включа-
ется в файл HTML.
Ага, вижу тег <script>... Слушаю и повинуюсь.
</script>Браузер, будь другом,
выполни для меня пару операций.
Но как объяснить браузеру, что он должен сделать? Это
как-то непривычно...
Хороший вопрос. Напомним, что HTML — язык разметки, который определяет структуру документа.А каскадные таблицы стилей (CSS) опреде-ляют внешний вид и расположение этих элементов. Таким образом, в коде HTML и CSS можно описать, как веб-страница долж-на строиться и отображаться, но добавить новое поведение в нем не удастся. Для этого вам понадобится язык сценариев. Для этого вам понадобится jQuery.
дальше � 41
знакомство с jquery
jQuery — библиотека
JavaScript, предназначенная
для изменения документов
веб-страниц «на ходу».
Çíàêîìüòåñü: jQuery (è JavaScript)!
Язык, используемый для передачи инструкций браузеру, на-зывается JavaScript. В каждом браузере имеется встроенный интерпретатор JavaScript, который получает инструкции из тегов <script> и преобразует их в операции с веб-страницей.
Чтобы передать инструкции интерпретатору, необходимо знать JavaScript. Не беспокойтесь! jQuery вам в этом поможет. jQuery — библиотека JavaScript, предназначенная для изменения доку-ментов веб-страниц «на ходу». Рассмотрим при-мер использования jQuery.
Интерпретатор JavaScript отслежива-
ет («прослушивает»)
события, происходящие
со страницей, — такие
как щелчок мышью.
Интерпретатор JavaScript тоже мо-жет отдавать брау-зеру команды.
Эй, браузер, обнови для меня этот элемент img!
Пользователь щелкнул мышью!
<script> $(document).ready(function(){ Когда документ веб-страницы будет готов,
выполнить следующие действия. $("button").click(function(){ $("h1").hide("slow");
$("h2").show("fast"); $("img").slideUp(); }); }); </script>
Возьми в руку карандаш Следующий сценарий динамически изменяет веб-страницу. Прочитайте каждую строку
и попробуйте предположить, что она делает, руководствуясь своими знаниями HTML и
CSS. Затем запишите краткое описание каждой строки справа. Если в чем-то не уверены —
попытайтесь угадать, это абсолютно нормально. Описание одной строки мы заполнили за вас.
42 глава 1
решение упражнения
Хороший вопрос. Чудеса какие-то, верно?Давайте взглянем на веб-страницу с точки зрения браузера. Итак, как же jQuery может изменять страницу из браузера?
Следующий сценарий динамически изменяет веб-страницу. Прочитайте каждую строку
и попробуйте предположить, что она делает, руководствуясь своими знаниями HTML и CSS.
Затем запишите краткое описание каждой строки справа. Если в чем-то не уверены —
попытайтесь угадать, это абсолютно нормально. Ниже приведено наше решение.
<script> $(document).ready(function(){ Когда документ веб-страницы будет готов,
выполнить следующие действия. $("button").click(function(){ При щелчке на любой кнопке сделать следую-
щее: $("h1").hide("slow"); Все элементы h1 медленно исчезают со стра-
ницы. $("h2").show("fast"); Все элементы h2 медленно появляются на
странице. $("img").slideUp(); Все элементы img скользят вверх и исчезают. }); Конец функции click.}); Конец функции ready.</script>
Но если я не обновляю страницу, как браузер узнает, что элемент нужно
скрыть или переместить вверх?
Возьми в руку карандаш Решение
дальше � 43
знакомство с jquery
×òî ïðîèñõîäèò â áðàóçåðå
Пора разобраться, что же в действительности происходит в браузере при отображении веб-страницы. Ваш браузер использует модель HTML DOM (Document Object Model) для преобразования простой разметки HTML и кода CSS в полноценную страницу с текстом, графикой, видеороликами и прочим замечательным контентом, который мы с таким удовольствием просматриваем.
index.html
Ядро визуализации браузера анализирует HTML и CSS для построения «документа» на базе HTML DOM (Document Object Model).
2
Браузер загружает файл HTML,полученный от сервера.
1
Браузер отображает построенную страни-цу в окне просмотра браузера.
3
Интерпретатор JS обращается к структу-ре DOM для внесения изменений в веб-страницу без ее перезагрузки.
4
index.html Версия страницы в формате DOM
Окно просмотра (viewport) — глав-ное окно браузера.
Все это происходит внутри браузера.
Интерпретатор JavaScript
Версия страницы в формате DOM
44 глава 1
строение DOM
Долгие годы структура DOM помогала HTML, CSS и JavaScript эффективно работать в сочетании друг с другом. DOM образует стандартный «скелет» страницы, который используется всеми современными браузерами для повы-шения эффективности просмотра. Структуру DOM часто сравнивают с дере-вом: у нее тоже есть корень и ветви, завершающиеся узлами. Или, если хотите, DOM напоминает рентгеновский снимок построенной страницы.
Ñêðûòàÿ ñòðóêòóðà âåá-ñòðàíèöû
На рентгеновском снимке врач видит скрытую структуру человеческого тела. Аналогичным образом DOM пред-ставляет скрытую структуру веб-страницы. Но в отличие от рентгенограмм JavaScript и jQuery могут использовать DOM для изменения структуры страницы.
html
head body
Тег <html> — «корень»
документа.
title div ul
«DOM Bones»
«Dem Bones»
li li li p img
Кроме узлов элемен-
тов, в структуру
DOM также входят
текстовые узлы.
Части DOM назы-ваются «узлами».
Внутренние узлы иерархии <html> называются «уз-лами элементов».
«Toe bone connected to your foot bone»
«Foot bone connected to your ankle bone»
«Ankle bone connected to yourleg bone»
дальше � 45
знакомство с jquery
На первый взгляд может показаться, что операции с DOM слишком сложны, но, к счастью, использование jQuery сильно упрощает их. Не забудьте: опе-рации jQuery тоже выполняются из кода JavaScript, но в куда более удобном виде. Предположим, вы хотите изменить код HTML, содержащийся в един-ственном элементе абзаца на странице.
Одно из главных преимуществ jQuery заключается в том, что библиотека позволяет работать с DOM, почти ничего не зная об этой структуре. Всю «черную работу» вы-полняет код библиотеки. В этой книге вы научитесь использовать JavaScript в соче-тании с jQuery. В главе 6 отношения между jQuery и JavaScript будут рассмотрены бо-лее подробно, а заодно вы повысите свою квалификацию в области JavaScript. А до этого момента все операции с DOM будут выполняться средствами jQuery.
jQuery óïðîùàåò ðàáîòó ñ DOM
document.getElementsByTagName("p")[0].innerHTML = "Change the page.";
for (i = 0; i <= 4; i++){ document.getElementsByTagName("p")[i].innerHTML="Change the page";}
$("p").html("Change the page.");
 îáû÷íîì êîäå JavaScript  jQuery
В jQuery используется «ме-
ханизм селекторов»; таким
образом, для получения эле-
ментов можно использовать
селекторы, как это делается
в CSS.
Операция выполняется
с основным документом.Получить эле-мент абзаца.
Заменить код HTML этого элемента значением в круглых скобках.
Получить все элементы с име-нем тега «p».
Выбрать нуле-вой элемент. Записать в код HTML этого элемента...
...это значение.
А сейчас пришло время опробовать jQuery и DOM в действии...
Или допустим, вы хотите изменить код HTML в пяти элементах абзацев нашей страницы:
$("p").html("Change the page.");
В цикле перебираем элементы,
которые требуется изменить.
Так как в jQuery использу-ются селекторы CSS, эта операция выполняется так же, как и предыдущая.
Получить теку-щий элемент.
46 глава 1
готовый код
<!DOCTYPE html><html><head> <title>jQuery goes to DOM-ville</title><style> #change_me { position: absolute; top: 100px; left: 400px; font: 24px arial;}
#move_up #move_down #color #disappear { padding: 5px;}</style><script src="scripts/jquery-1.6.2.min.js"></script></head><body> <button id="move_up">Move Up</button> <button id="move_down">Move Down</button> <button id="color">Change Color</button> <button id="disappear">Disappear/Re-appear</button>
<div id="change_me">Make Me Do Stuff!</div> <script> $(document).ready(function() { $("#move_up").click( function() { $("#change_me").animate({top:30},200); });//end move_up $("#move_down").click( function() { $("#change_me").animate({top:500},2000); });//end move_down $("#color").click( function() { $("#change_me").css("color", "purple"); });//end color $("#disappear").click( function() { $("#change_me").toggle("slow"); });//end disappear });//end doc ready </script></body></html>
Введите следующий код в текстовом редакторе. Сохраните его, откройте в браузере и проверьте, как работает каждая кнопка. (И раз уж на то пошло, просмотрите код и попробуйте разо-браться, как он работает...)
index.html
Готово к употреблению
дальше � 47
знакомство с jquery
Манипуляции jQuery со страницей выглядят довольно впечатляюще, верно? Важ-но помнить, что при нажатии кнопок исходный код HTML и CSS остается неиз-менным. Как же jQuery творит все эти чудеса? Взгляните на схему.
Êàê ýòî ðàáîòàåò?
Интерпретатор JavaScript не изменяет ис-
ходные файлы HTML и CSS. Он вносит изме-
нения в представление страницы в формате
DOM, хранящееся в памяти браузера.
Обнаружено нажатие кнопки.
Пользователь нажимает кнопку.1
Интерпретатор JavaScript
Интерпретатор JavaScript об-наруживает событие щелчка и запускает функцию, связанную с этим событием.
2
Интерпретатор JavaScript изменяет представление страницы в структуре DOM.
3
Пользователь ви-дит, как элемент перемещается вверх по странице.
4
Версия страницы в формате DOM
Это вы видите в браузере
Понятно — просто скажи, что
нужно сделать.
Засценой
Переместить элемент вверх.
48 глава 1
функции jquery
Если разместить здесь селектор CSS, то jQuery вернет набор элементов, соответствующих этому селектору.Это самый распространенный вари-ант использования функции.
$( )
А для чего нужны знаки $ в коде?
jQuery( )
Ôóíêöèÿ jQuery (è åå ñîêðàùåííàÿ çàïèñü)
Знак доллара со скобками — это сокращенная запись функ-ции jQuery. Мы используем ее вместо записи «jQuery()», когда хотим обозначить функцию jQuery (ее также назы-вают «оберткой»).
Знак доллара ($) показывает, сколько денег вы сможете за-рабатывать со своими новыми навыками jQuery... Шутка — однако знак $ играет очень важную роль в мире jQuery.
Оба имени, короткое и длинное, обозначают одно и то же: длинный блок программного кода. В этой книге будет использоваться сокращенная запись. В круглых скобках функции jQuery могут передаваться аргументы трех видов.
$( )
Функция jQuery возвраща-
ет элементы, определяе-
мые условиями в круглых
скобках.
Сокращенная запись для jQuery. Вместо шести символов, образующих имя «jQuery», до-статочно ввести всего один символ.
Если в скобках заклю-чена строка HTML, то вы сможете добав-лять элементы DOM в страницу «на ходу».
На этот вариант пока не обращай-те внимания. Он будет рассмотрен в следующих главах.
дальше � 49
знакомство с jquery
jQuery âûáèðàåò ýëåìåíòû ïî òåì æå ïðàâèëàì, ÷òî è CSS
Вы уже знаете о jQuery больше, чем может показаться на первый взгляд. Для выбора элементов в jQuery используются селекторы — те же, кото-рые вы использовали в CSS. Если вы подзабыли, как работают селекто-ры CSS, краткая сводка поможет вам освежить память.
Это селектор элементов (он же — селектор тегов). Он выбирает все элементы h1 в документе HTML.
h1 { text-align: left;}
.my_class { position: absolute;}
Все это пра-вила CSS. Селектор классов позволяет
выбрать сгруппированные элементы.
Это свойство CSS… …а это его значение.
Обозначение
класса CSS всег-
да начинается
с точки.
#my_id { color: #3300FF;}
А это селектор идентификаторов. Он используется в тех случаях, когда нужно выбрать один — и только один! — элемент.
Идентификатор CSS всегда начина-ется с «решетки» (знак #).
50 глава 1
похоже на стили
Селектор элементов jQuery
Метод
Метод
$("h1").hide();
$(".my_class").slideUp();
$("#my_id").fadeOut();
Метод
В jQuery селекторы, используемые в CSS для стилевого оформления стра-ницы, используются для выполнения операций с элементами страницы.
Селектор элементов
h1 { text-align: left;}
.my_class{ position: absolute;}
#my_id { color: #3300FF;};
Селектор идентифи-каторов jQuery
Селектор классов
Селектор идентификаторов
Ñåëåêòîðû: ñòèëè è ñöåíàðèè
Ñåëåêòîð CSS Ñåëåêòîð jQuery
Скрывает все элементы h1 на странице.
Сдвигает вверх
все элементы,
входящие в класс
CSS my_class.
Команда «раство-ряет» элемент с идентификатором CSS my_id до тех пор, пока он не станет невидимым.
Селектор классов jQuery
Селекторы CSS выбирают элементы для при-
менения стилей; селекторы jQuery выбирают
элементы для добавления нового поведения.В главе 2 (и в остальных гла-вах) мы продолжим объединять селекторы с методами.
дальше � 51
знакомство с jquery
img{ float:left; height:350px; text-align:center; border: solid #000 5px;}
Èñïîëüçîâàíèå ñåëåêòîðîâ jQuery
$("img")
img
" "
$( )
В этом примере ис-пользуется элемент img, но с таким же успехом его можно заменить другими элементами.
Селекторы опреде-ляются в строковом формате, поэтому их необходимо заклю-чать в кавычки.
Селекторы передаются функции jQuery в сокращенной записи.
Библиотека jQuery за-прашивает элементы средствами JavaScript…
Эй, jQuery, ты можешь вернуть мне все элементы
img на странице?
Как подсказывает само название, библиотека jQuery предназначена для создания запросов (querying). Вы что-то описываете при помощи селектора, а интерпретатор JavaScript запраши-вает это «что-то» у структуры DOM. Если запрашиваемый элемент содержит вложенные элемен-ты, то jQuery вернет и их. Давайте рассмотрим селектор jQuery, чтобы вы лучше поняли, как он работает.
Это селектор. Для выбора элементов в библиотеке jQuery используется способ, знакомый нам по CSS. Селектор CSS
Интерпретатор JavaScript
Версия страницы в формате DOM
DOM, верни мне все элементы img
на странице.
…и возвращает их.
О том, что де-лать с полученными элементами, будет рассказано в главе 4. А пока нас интере-сует только меха-низм выбора этих элементов.
Держи.
52 глава 1
вы говорите на jquery?
jQuery â ïåðåâîäå
$("button").click(function(){} });
...вы должны кое-что сделать для меня.
...когда поль-зователь щелкнет на вас...
Слушайте, элементы button...
Чтобы показать вам, как легко пользоваться jQuery, мы разберем несколько выражений на языке jQuery, которые могли бы вам при-годиться в ваших путешествиях по стране DOM.
$("p").hide;
...станьте невидимыми.
Каждая команда jQuery
должна завершаться
символом «точка с за-
пятой».
Эй, элементы p (т. е. элементы абзацев)...
$("#myTop").css({" background-color":"blue"});
…цвет фона… …синий.
…задай для себя правило CSS…
Элемент с идентифика-тором myTop…
<p> Poof!</p>
<div id="myTop”></div>
Текст, заключенный в элементах абза-
цев, исчезает.
Когда пользо-ватель щелкает на мне, я выполняю все коман-ды jQuery в фигурных
скобках.
>>>>>>>>>>>>>> PPPPPPPPPPPPPPPooooooooooooooooooooooooooofffffffffffffff!!!!!!!!!!!!!!
Окрашивается в синий цвет.
дальше � 53
знакомство с jquery
СТАНЬ браузеромПредставьте себя на месте браузера. Обведите
кружком элементы HTML (справа), на которые
повлияет выполнение команды jQuery (слева).
<p>Проснувшись однажды утром после беспокойного сна. . .</p>
<p>Грегор Замза обнаружил, что он у себя в постели превратился в страшное насекомое.</p>
<p>Лежа на панцирнотвердой спине, он видел, стоило ему приподнять голову. . . </p>
$("p").hide();
Команда jQuery Элементы HTML
<p id="mytext">Проснувшись однажды утром после беспокойного сна. . .</p>
<p id="mytext">Грегор Замза обнаружил, что он у себя в постели превратился в страшное насекомое.</p>
<p>Лежа на панцирнотвердой спине, он видел, стоило ему приподнять голову. . . </p>
$("p#mytext").show();
<span class="Italian">Nel Mezzo del cammin di nostra vita</span>
<span class="English">In the middle of this road called "our life"</span> <span class="Italian">mi ritrovai per una selva oscura</span>
$("span.Italian").toggle();
54 глава 1
решение упражнения
СТАНЬ браузером — решениеПредставьте себя на месте браузера. Обведите
кружком элементы HTML (справа), на которые
повлияет выполнение команды jQuery (слева).
<p>Проснувшись однажды утром после беспокойного сна. . .</p>
<p>Грегор Замза обнаружил, что он у себя в постели превратился в страшное насекомое.</p>
<p>Лежа на панцирнотвердой спине, он видел, стоило ему приподнять голову. . . </p>
$("p").hide();
Команда jQuery Элементы HTML
<p id="mytext">Проснувшись однажды утром после беспокойного сна. . .</p>
<p id="mytext">Грегор Замза обнаружил, что он у себя в постели превратился в страшное насекомое.</p>
<p>Лежа на панцирнотвердой спине, он видел, стоило ему приподнять голову. . . </p>
$("p#mytext").show();
<span class="Italian">Nel Mezzo del cammin di nostra vita</span>
<span class="English">In the middle of this road called "our life"</span> <span class="Italian">mi ritrovai per una selva oscura</span>
$("span.Italian").toggle();
дальше � 55
знакомство с jquery
В: Зачем было создавать jQuery, если библиотека только использует JavaScript? Разве одного JavaScript недостаточно?
О: JavaScript хорошо подходит для многих задач (и особенно для манипуляций с DOM), но решение получается довольно сложным. Низкоуровневые операции с DOM — дело в лучшем случае не-простое. Именно здесь на помощь приходит jQuery: библиотека скры-вает многие сложности, связанные с операциями с DOM, и благодаря ей самые впечатляющие эффекты создаются на удивление просто. (Библиотеку jQuery создал Джон Резиг; дополнительная инфор-мация об авторе доступна по по адресу http://ejohn.org/about).
В: Зачем нужны все эти знаки доллара?
О: Это просто сокращенное обозначение, чтобы вам не при-ходилось снова и снова вводить «jQuery»! Впрочем, если вы ра-
ботаете с другими языками на стороне клиента, полная запись jQuery() поможет избежать конфликтов имен.
В: Ранее вы уже упоминали о «клиентских сценариях». Что это такое?
О: Веб-разработчики часто назы-вают браузер клиентом, потому что он использует данные, полу-ченные с (веб-)сервера. Клиентский язык сценариев управляет работой браузера, тогда как серверные язы-ки отдают инструкции серверу. Эта тема более подробно рассматрива-ется в главах 8 и 9.
В: Как появилась модель DOM?
О : Хороший вопрос. Веб-дизайнеры и разработчики устали от несовместимости браузеров и решили, что им необходим стан-дартный механизм добавления по-ведения и взаимодействия со стра-ницами в любом браузере. Комитет W3C (World Wide Web Consortium)
разработал стандарт DOM при уча-стии многочисленных заинтересо-ванных групп. За дополнительной информацией обра щайтесь по адресу http://w3.org/dom.
В: Загрузка jQuery доступна в двух вариантах: рабочая вер-сия и версия для разработчи-ков. Чем они отличаются друг от друга?
О: Рабочая версия более компак-тна, из нее удалены избыточные символы и пробелы. Она оптими-зирована для достижения макси-мального быстродействия в ходе реальной эксплуатации, но в ней труднее разобраться. В версии для разработчиков расставлены удобные пробелы, она лучше чи-тается. Эта версия предназначена для программистов, которые хотят покопаться в коде jQuery с целью его изменения и даже расширения (раз уж это проект с открытым ис-ходным кодом!).
частоЗадаваемые
вопросы
56 глава 1
jquery приходит на помощь
Âàø ïåðâûé ïðîåêò ñ jQuery
Вы только что поступили на должность веб-разработчика в Фонд спасения домашних пи-томцев. Группа маркетинга хочет запустить ежегодную кампанию по привлечению средств, в которой должна быть задействована переработанная версия прошлогодней веб-страницы «Поможем нашим пушистым друзьям». Вам выдали снимок экрана из прошлогодней кампании с подробными инструкциями по поводу того, что должна делать страница.
Джош из отдела марке-тинга требует улучшения интерактивности.
Никто не хочет подвести отдел маркетинга в первый же день — с этими ребятами лучше не ссориться! Для начала посмотрим, как была реализована старая версия страницы.
Прошлогоднюю страницу нужно доработать. Сейчас по-сетитель щелкает на кнопке, и на экране появляется временная картинка — но она не остается на странице. Мы хотим, чтобы при первом щелчке на кнопке изображение появлялось, а при
повторном — исчезало со страницы.
Когда посетитель Когда посетитель щелкает здесь . . .щелкает здесь . . .
. . . эта секция стано-. . . эта секция стано-вится видимой и уве-вится видимой и уве-личивается до размеров личивается до размеров изображения.изображения.
Примечание:Примечание:И все это должно происходить И все это должно происходить внутри страницы (то есть внутри страницы (то есть кнопка не должна открывать кнопка не должна открывать новую страницу HTML).новую страницу HTML).
Показать «пуши-стого друга»
К тому же изображение просто возникает из ничего. Нельзя ли чтобы это происходило помед-леннее, а картинка проявлялась
постепенно?
А его начальнику нужны визуальные эффекты.
дальше � 57
знакомство с jquery
a:link img, a:visited img {
display:none;
}
a:hover img, a:active img {
display:block;
}
a{
text-decoration:none;
color: #000;
}
<!DOCTYPE html><html> <head>
<title>Furry Friends Campaign: jQuery Proof-of-Concept</title>
<link rel="stylesheet" type="text/css" href="styles/my_style.css">
</head>
<body>
<div id="showfriend">
<a href="#">Our Furry Friends Need Your Help
<img src="images/furry_friend.jpg">
</a>
</div>
У якорного тега имеются состояния «hover» и «active», заданные в CSS.Пользователь наводит указатель мыши на ссылку — изображение появляется.
index.html
my_style.css
Возьми в руку карандашПрежде чем разбираться с тем, как включить в страницу функциональность
jQuery, стоит посмотреть, как выглядел код HTML и CSS предыдущей версии.
Ниже приведено содержимое файла из прошлогодней кампании. Найдите
элементы, которые, по вашему мнению, понадобятся вам в реализации.
Напишите рядом с каждым элементом, что необходимо сделать для выполнения
требований отдела маркетинга. Первое описание мы заполнили за вас.
58 глава 1
решение упражнения
Прежде чем разбираться с тем, как включить в страницу функциональность
jQuery, стоит посмотреть, как выглядел код HTML и CSS предыдущей версии.
Ниже приведено содержимое файла из прошлогодней кампании. Найдите
элементы, которые, по вашему мнению, понадобятся вам в реализации.
Напишите рядом с каждым элементом, что необходимо сделать для
выполнения требований отдела маркетинга. Не беспокойтесь, если ваши
ответы где-то отличаются от наших.
a:link img, a:visited img {
display:none;
}
a:hover img, a:active img {
display:block;
}
a{
text-decoration:none;
color: #000;
}
о
<!DOCTYPE html><html> <head>
<title>Furry Friends Campaign: jQuery Proof-of-Concept</title>
<link rel="stylesheet" type="text/css" href="styles/my_style.css">
</head>
<body>
<div id="showfriend">
<a href="#">Our Furry Friends Need Your Help
<img src="images/furry_friend.jpg">
</a>
</div>
У якорного тега имеются состоя-ния «hover» и «active», заданные в CSS. Пользователь наводит указатель мыши на ссылку — изображение появляется.
index.html
my_style.css
Изображение встроено в якорный тег. Оно не должно отображаться до тех пор, пока пользователь не щелкнет на ссылке якорного тега.
Этот селектор CSS задает свойству display вложенного изображения значение «none», чтобы оно оставалось скры-тым при загрузке страницы.
Когда пользователь наводит указатель мыши или щелкает на якорном теге, свойство display элемента img при-нимает значение «block». Изображение мгновенно появляется на экране.
Возьми в руку карандаш Решение
дальше � 59
знакомство с jquery
Преобразуем в область div с отслеживанием щелчков.
Изображение тоже оформ-ляется в виде области div, которая изначально нахо-дится в скрытом состоянии.
Мы присвоим этой области идентификатор picframe.
Можно, но сначала нужно подготовиться. Прежде чем использовать jQuery для реализации всех эффектов, которые желает видеть отдел марке-тинга, мы должны убедиться в том, что у jQuery есть все необходимое для работы. Как вы уже знаете, одна из главных задач jQuery — манипуляции с элементами HTML, поэтому нам понадобится хорошая структура. Для выбора элементов jQuery использует те же селек-торы, что и CSS; следовательно, нам также понадо-бятся хорошо определенные стили.
Âåðíåìñÿ ê òðåáîâàíèÿì
Размышляя о структуре, всегда полезно вернуться на шаг назад и понять, что же вы, собственно, пытаетесь построить. Отдел маркетинга хочет, чтобы изображе-ние опускалось и проявлялось при щелчке в области страницы «Show Me the Furry Friend of the Day». Какие изменения в HTML и CSS для этого нужно внести?
Пора браться за дело? Пишем код jQuery для всей нужной
функциональности?!
60 глава 1
наводим порядок
<!DOCTYPE html><html><head> <title>Furry Friends Campaign</title> <link rel="stylesheet" type="text/css" href="styles/my_style.css"> </head> <body> <div id="clickMe">Show Me the Furry Friend of the Day</div> <div id="picframe"> <img src="images/furry_friend.jpg"> </div> <script src="scripts/jquery-1.6.2.min.js"></script> <script> $(document).ready(function(){ $("#clickMe").click(function() { }); }); </script> </body></html>
#clickMe { background: #D8B36E; padding: 20px; text-align: center; width: 205px; display: block; border: 2px solid #000;}
#picframe { background: #D8B36E; padding: 20px; width: 205px; display: none; border: 2px solid #000;}
Ïîäãîòîâêà ôàéëîâ HTML è CSS
Прежде чем браться за написание команд jQuery, следует подумать, какие изменения необходимо внести в файлы HTML и CSS. Откройте файлы jQuery главы 1 (если вы еще не загрузили их, обращайтесь к разделу «Как работать с книгой» во Введении). Найдите среди файлов главы 1 папку Begin. Включите в файлы код, выделенный ниже жирным шрифтом.
Этот фрагмент создает область div, отслежи-вающую щелчки мышью. Приме-ним к области стилевое оформ-ление в файле CSS, чтобы она по внешнему виду не отличалась от области div с идентификато-ром picframe.
Область div с идентифика-тором будет «скользить», открывая скры-тое изображе-ние.
Изображение furry_friend.jpg вложено в элемент picframe.
В селекторе picframe за-дается значение «display: none», чтобы картинка не отображалась при за-грузке страницы.
Этот фрагмент определяет
оформление области clickMe,
чтобы она не отличалась по
виду от области div с иденти-
фикатором picframe.
index.html
my_style.css
Задание!
дальше � 61
знакомство с jquery
Итак, файлы HTML и CSS готовы. Пора повнимательнее присмотреться к коду, заключенному в теги <script>.
$(document).ready(function(){ $("#clickMe").click(function() {
});});
Точка отделяет селектор от метода.
Точка с запятой завершает конструкцию jQuery click.
Селектор идентификаторов для области clickMe.
Кнопка с идентификатором clickMe связывается с событием click. После этого кнопка начина-ет отслеживать щелчки мышью.
Код, который должен выполняться при нажатии кнопки, заключается в фигурные скобки («блок кода»).
DOM
…сделай кое-что
для меня.Эй, DOM…
…когда загрузка за-вершится и все будет готово к работе…
А эта точка с запятой завершает функцию jQuery ready.
При первой же возможности я начну выполнять код в фигур-
ных скобках!
В описании встречается много новых терминов.
Вскоре все эти события, методы и функции будут рассмотрены бо-лее подробно.
Код под увеличительным стеклом
Р А СС Л А Б Ь Т Е С Ь
62 глава 1
добавление эффектов
Но наша страница пока еще не делает
ничего нового!
Верно. Разметка HTML и код CSS готовы; пора переходить к jQuery.Вместо мгновенного появления содержи-мое picframe должно разворачиваться и и постепенно проявляться на странице. К счастью, создатели jQuery предусмотре-ли эффекты для управления обоими визу-альными действиями. Эффектам jQuery в книге посвящена целая глава (глава 5), так что не старайтесь запомнить все сейчас. Начнем с эффекта скольжения.
$("div").slideToggle();
Метод slideUp изменяет свойство height элемента, пока оно не станет рав-ным 0, после чего скрывает элемент.
Действие slideToggle означа-ет: «Если элемент свер-нут, развернуть его, а если развернут — свернуть».
Ïîåõàëè…Начнем с эффекта скольжения, которого от нас требует начальник группы маркетин-га. Существуют три варианта реализации скольжения:
$("div").slideUp(); $("div").slideDown();
Метод slideDown изменя-ет свойство height эле-мента от 0 до значения, заданного в стиле CSS.
дальше � 63
знакомство с jquery
$("img").fadeIn();
То, что должно проявляться на странице: в данном случае элемент img.
Проявляющийся элемент постепенно переходит из состояния полной прозрач-ности в состояние полной непрозрачности.
Ýôôåêòû èçìåíåíèÿ ïðîçðà÷íîñòè
Мы также хотим, чтобы изображение плавно переходило от полной прозрачности к полной видимости. И для этой категории эффектов в jQuery тоже существуют специальные методы. Имена этих мето-дов очень похожи на имена методов скольжения: FadeIn, FadeOut, FadeTo и FadeToggle. В нашем примере будет использоваться метод FadeIn, управляющий прозрачностью элементов HTML.
Как вы думаете, сколько команд jQuery потребуется для достижения нужного эффекта?
Запишите эти команды на листке бумаги. Если не уверены, хотя бы попробуйте сформулировать их суть словами; постепенно мы научим вас мыслить понятиями jQuery.
Вы можете задать скорость про-явления, указывая нужное значение в круглых скобках. Величина обычно задается в миллисекундах (мс).
Мозговой
штурм
64 глава 1
проще некуда
È ýòî âñå?
Невероятно, но для реализации этих эффектов доста-точно написать всего две строки кода jQuery. Теперь вы понимаете, почему у jQuery так много поклонников? Включите фрагмент, выделенный жирным шрифтом, в файл index.html — вот и все!
<!DOCTYPE html>
<html>
<head>
<title>Furry Friends Campaign</title>
<link rel="stylesheet" type="text/css" href="styles/my_style.css">
</head>
<body>
<div id="clickMe">Show me the Furry Friend of the Day</div>
<div id="picframe">
<img src="images/furry_friend.jpg">
</div>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script>
$(document).ready(function(){
$("#clickMe").click(function() {
$("img").fadeIn(1000);
$("#picframe"). slideToggle("slow");
});
});
</script>
</body>
</html>
index.html
В jQuery важно выстроить эффекты в такой по-следовательности, чтобы они не мешали друг другу. Позднее мы еще вернемся к этой проблеме.
Значения в круглых скобках обеспечивают дополнитель-ную настройку эффектов. За подробностями обращай-тесь к главе 5.
Сначала к изобра-
жению применяется
эффект проявления.
Задание!
дальше � 65
знакомство с jquery
Откройте страницу в своем любимом браузере и убедитесь в том, что все работает.
Щелкните здесь.
Изображение постепенно проявляется и разворачива-ется на стра-нице.
Тест-драйв
Будьте осторожны!
Проверьте в разных браузерах.
Да, jQuery одинаково работает во всех браузерах — но это не означает, что во всех браузерах будут одинаково работать стили, определенные в файле CSS, или динамические стили, примененные к элемен-там страницы!
66 глава 1
друг животных
Ïóøèñòûå Äðóçüÿ ñïàñåíû
Потрясающе смотрится — и ты справился так быстро!
Вы успешно справились с поставленной задачей — для этого было достаточно слегка изменить HTML и CSS и добавить пару строчек jQuery. Благодарные зверюшки вас не забудут…
Новая кампания приносит хоро-шие результаты. А это значит, что
у нас будет больше денег для спасения животных. Спасибо!
дальше � 67
знакомство с jquery
Âàø èíñòðóìåíòàðèé jQuery
Глава 1 осталась позади, а ваш творческий инстру-ментарий расширился: в него добавилась основная функция jQuery, селекторы, события click и эффекты изменения прозрачности.
Функция jQuery
Используется для выбора элементов
страницы HTML, с которыми выпол-
няется операция.
Сокращенная запись $ избавляет
вас
от необходимости снова и снова на
-
бирать «jQuery».
Функции jQuery могут передаваться
селекторы, код HTML и даже объек-
ты JavaScript.
Эффекты изменения прозрач-
ности
К выбранному элементу можно при-
менять различные эффекты изменения
прозрачности с использованием мето-
дов FadeIn, FadeOut, FadeTo и FadeToggle.
Эффекты изменения прозрачности мо-
гут применяться к любым элементам:
тексту, графике и т. д.
Чтобы управлять скоростью изменения,
укажите время (в миллисекундах) в кру-
глых скобках в конце команды.
Селектор В jQuery, как и в CSS, для выбора элементов используются селек-торы.
Селекторы jQuery позволяют идентифицировать практически любые элементы HTML.
ГЛА
ВА 1
2 Селекторы и методы
Хватай и действуй
jQuery помогает выбирать элементы веб-страниц и выполнять с ними всевозможные операции. В этой главе более подробно рассмотре-ны селекторы и методы jQuery. Селекторы jQuery выбирают элементы страницы, а методы выполняют операции с этими элементами. Библиотека jQuery, словно сборник магических заклинаний, позволяет изменять окружающую реальность. Вы можете заставить изображение исчезнуть или появиться из ниоткуда или же выбрать фрагмент текста и анимировать изменение размера его шрифта... Но довольно разговоров — хватайте элементы веб-страниц и действуйте!
Крошка, мои селекто-ры и методы способны
творить настоящие чудеса с элементами твоих
веб-страниц...
70 глава 2
репутация растет
От: ЭмилиТема: Рекламная акция «Прыгаем от радости»!
Привет,
Читала у тебя в Твиттере, что ты занялся интерактивным веб-программированием.
Надеюсь, ты поможешь мне с реализацией некоторых интерактивных возможно-
стей для рекламной акции «Прыгаем от радости» на моем сайте. Я хочу, чтобы
посетители могли получить скидку перед оформлением своего заказа. Так поль-
зователи будут взаимодействовать с сайтом и проводить на нем больше времени
(и хочется надеяться, будут больше покупать!).
Страница должна состоять из четырех областей, по одному из четырех изображе-
ний в каждой. Когда пользователь щелкает в одной из областей, под изображе-
нием в этой области появляется сообщение «Размер вашей скидки:» и случайное
значение (от 5 до 10 процентов). Если пользователь щелкает снова, то старое
сообщение исчезает и появляется новое.
Прилагаю набросок того, как это все должно выглядеть.
Сможешь помочь??
--Эмили
Ïîäðóãà ïðîñèò òåáÿ ïîìî÷ü îôîðìèòü ñàéò
Вы получили сообщение от своей подруги — профессионального фотогра-фа-портретиста. Она хочет провести рекламную акцию «Прыгаем от радо-сти» по получению скидок, и ей нужна ваша помощь в оформлении сайта.
дальше� 71
селекторы и методы
Список задач:
1.
2.
3.
4.
5.
×òî òðåáóåòñÿ îò ïðîåêòà?
Эмили — хороший фотограф, но ее запрос выглядит довольно туманно. Давайте повнимательнее присмотримся к сообщению и попробуем понять, чего же она, собственно, хочет. Прежде чем браться за написание кода jQuery, необходимо предельно четко выяснить, что же требуется от проекта (и от пользователя).
Выделите из сообщения список конкретных задач, которые долж-
но решать веб-приложение. По этому списку мы сможем убедиться
в том, что наше веб-приложение отвечает потребностям заказчика.
Возьми в руку карандаш
Преобразование пользовательских запросов в непосредственные требования проекта — важный навык, который совершенствуется со временем и практикой.
72 глава 2
решение упражнения
Список задач:
1.
2.
3.
4.
5.
Выделите из сообщения список конкретных задач, которые должно
решать веб-приложение. По этому списку мы сможем убедиться в
том, что наше веб-приложение отвечает потребностям заказчика.
Приводим наше решение.
Страница должна состоять из четырех областей. Каждая область содержит одно изображение.
Области должны реагировать на щелчки мышью.
Нам понадобится сообщение, состоящее из текста («Размер ва-шей скидки:») и случайного значения (от 5 до 10 процентов).
Когда пользователь щелкает в одной из областей, под изображе-нием в этой области должно появляться сообщение.
Если пользователь щелкает снова, то старое сообщение исчезает и появляется новое.
Отлично, с требованиями разобрались — давайте уже браться за jQuery!
Стоп! Не надо торопиться!Начинать работу над каждым проектом jQuery с про-работки требований — безусловно полезная при-вычка. Но прежде чем приступать к написанию кода jQuery, необходимо немного поработать над струк-турой и стилями. Мы сделали это в главе 1, а теперь перед переходом к jQuery придется потрудиться еще основательнее.
Возьми в руку карандаш Решение
дальше� 73
селекторы и методы
Íà÷èíàåì ñ div
На странице должны находиться четыре области, реагирующие на щелчки мышью; начнем с создания этих областей. Самый полезный и универсальный элемент HTML для наших целей — тег <div>. Он очень хорошо подходит для определения струк-туры, так как является блочным элементом. Кроме того, внешний вид и поведение элементов div удобно определяется посредством применения стилей.
Тег для включения библиотеки jQuery, версия 1.6.2.Тег <div> с идентификатором header.Тег <div> с идентификатором main.Разместите в каждом из четырех элементов div, вложенных в main, от-дельное изображение (графические файлы можно загрузить по адресу www.thinkjquery.com/chapter02/images.zip).
<html>
<head>
<title>Jump for Joy</title>
<link href="styles/my_style.css" rel="stylesheet">
</head>
<body>
<h2>Jump for Joy Sale</h2>
</div>
<div><img src="images/jump1.jpg"/></div>
<div> </div>
<div> </div>
<div> </div>
</div>
<script > </script> </body>
</html>
index.html
div{
float:left;
height:245px;
text-align:left;
border: solid #000 3px;
}
#header{
width:100%;
border: 0px;
height:50px;
}
#main{
background-color: grey;
height: 500px;
}
my_style.css
УпражнениеОткройте свой любимый текстовый редактор и создайте необходимые файлы HTML и CSS. В приведенной ниже заготовке кода отсутствуют некоторые ключевые элементы. Включите в страницу пункты следующего списка, вычеркивая их по мере выполнения.
74 глава 2
решение упражнения
<html>
<head>
<title>Jump for Joy</title>
<link href="styles/my_style.css" rel="stylesheet">
</head>
<body>
<h2>Jump for Joy Sale</h2>
</div>
<div><img src="images/jump1.jpg"/></div>
<div> </div>
<div> </div>
<div> </div>
</div>
<script > </script> </body>
</html>
Откройте свой любимый текстовый редактор и создайте файлы HTML и CSS, необходи-мые для этого упражнения. В приведенной ниже заготовке кода отсутствуют некоторые ключевые элементы. После включения пунктов списка ваша страница должна выглядеть так, как показано в следующем решении.
Тег для включения библиотеки jQuery, версия 1.6.2.Тег <div> с идентификатором header.Тег <div> с идентификатором main.Разместите в каждом из четырех элементов div, вложенных в main, отдельное изображение.
index.html
div{
float:left;
height:245px;
text-align:left;
border: solid #000 3px;
}
#header{
width:100%;
border: 0px;
height:50px;
}
#main{
background-color: grey;
height: 500px;
}
my_style.css
<div id="header">
<div id="main">
<img src="images/jump2.jpg">
<img src="images/jump3.jpg">
<img src="images/jump4.jpg">
<script src="scripts/jquery-1.6.2.min.js"></script>
Ваши файлы HTML и CSS
должны выглядеть так.
Элемент div с иден-
тификатором header
Элемент div c иден-тификатором main
Включение библиотеки jQuery.
Элементы div для изображений.
дальше� 75
селекторы и методы
Откройте страницу в своем любимом браузере и убедитесь в том, что все работает правильно. С этим наглядным примером вам будет проще понять, как должна работать итоговая версия страницы.
Страница содержит четыре области с изображе-ниями. Как заставить эти области реагировать на щелчки мышью?
Элемент div с иденти-фикатором header.
Элемент div с идентифи-катором main содержит… …четыре элемента
div с изображениями.
Тест-драйв
Мозговой
штурм
76 глава 2
событие click
$("p").click( function() {
alert("You rang?");
});
Как мы уже знаете, организовать отслеживание события click элементом в jQuery совсем не сложно.
При щелчке на элементе страницы происходит событие, которое может привести к выполнению функций. Позднее события и функции будут рассмотрены более подробно, а пока давайте посмотрим, как событие click работает с те-гами абзацев (или тегами <div>).
Ñîáûòèå click ïîä óâåëè÷èòåëüíûì ñòåêëîì
Элемент, с которым
связывается событие
click.
Функция объединяет опе-
рации, которые должны
выполняться при обнару-
жении события.
Здесь мы сообщаем интерпретатору JS, что элементы абзацев должны что-то делать, когда пользователь щелкает на них мышью.
Закрывающая фигур-ная скобка завершает «блок» кода.
Открывающая фигурная скобка начинает «блок» программного кода. Блок можно сравнить с абзацем текста: абзац состоит из строк текста, блок состоит из строк кода.
Так как функция заключена в кру-глые скобки, отно-сящиеся к событию click, она будет выполняться при выполнении поль-зователем щелчка мышью.
Команда alert помо-жет нам убедиться в том, что функция была вызвана правильно.
Текст, заключенный в кавычки, появится в новом окне.
дальше� 77
селекторы и методы
Сложите из магнитов фрагмент кода, после выполнения которого
элементы div станут реагировать на щелчки мышью. При щелч-
ке на div функция JavaScript alert должна выводить текст «You
clicked me». Мы уже расставили несколько магнитов по местам.
("click(
function()
</script>
$(document)
.ready(
{
{
");
").
function()
alert
});
div
$("
});
<script>
You clicked me.
Развлечения с магнитами
78 глава 2
решение упражнения
("
click( function()
</script>
$(document) .ready( {
{
");
").
function()
alert
});
div$("
});
<script>
"You clicked me.
Убеждаемся в том, что страница гото-ва к взаимодействию с пользователем.
Выводим окно сообщения,
чтобы проверить, как ра-
ботает функция click.
Закрываем click для элемента div.
Закрываем ready.
Закрываем тег <script>.
Связываем с тегами <div>
событие click.
Открываем тег
<script>.
Сложите из магнитов фрагмент кода, после выполнения которого
элементы div станут реагировать на щелчки мышью. При щелч-
ке на div функция JavaScript alert должна выводить текст «You
clicked me».
Развлечения с магнитами
дальше� 79
селекторы и методы
Используя код из решения с магнитами на предыдущей странице, включите этот сценарий в свой файл HTML. Не забудьте, что он должен быть заключен в тег <script>!
Âêëþ÷åíèå ìåòîäà click â ñòðàíèöó
<html>
<head>
<title>Jump for Joy</title>
<link href="styles/my_style.css" rel="stylesheet">
</head>
<body>
<div id="header">
<h2>Jump for Joy Sale</h2>
</div>
<div id="main">
<div><img src="images/jump1.jpg"/></div>
<div><img src="images/jump2.jpg"/></div>
<div><img src="images/jump3.jpg"/></div>
<div><img src="images/jump4.jpg"/></div>
</div>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script > $(document).ready(function() {
$("div").click(function() {
alert("You clicked me.");
});//end click function
});//end doc ready
</script>
</body>
</html>
index.html
Функция alert от-крывает в браузере окно с сообщением. Мы будем использо-вать ее для проверки результатов вклю-чения в код новых переменных, функций и т. д.
Добавьте эти строки между те-гами <script>, чтобы
области div реаги-ровали на щелчки мышью.
Некоторые программисты добавляют
комментарии, которые помогают опреде-
лить, к какой команде относятся фигурные
и круглые скобки. Впрочем, использование
комментариев — вопрос стиля программи-
рования, и выбор исключительно за вами.
Задание!
80 глава 2
тест-драйв
Откройте страницу в своем любимом браузере и убедитесь в том, что все правильно работает. Если щелкнуть на изображении, на странице появляется окно сообщения.
Окно сообщения, добавленное
нами в программу. Как видите,
функция click работает.
Интерпретатор JS дела-
ет в точности то, что
мы требуем. Он выбирает
все области div… …и связывает каждую область
с методом click.
$("div").click( );
Хммм, действительно. Кажется, мы немного увлеклись со щелчками. Давайте снова вернемся к событию click.
Да, но сообщение появляется всегда, где бы я ни щелкала. Почему
так происходит?
Чтобы получить сообщение, необязательно даже щелкать на изо-бражениях. В структуре нашей страницы используются элементы div, вложенные в другие элементы div; при щелчке на них браузер думает, что вы щелкнули на обоих элементах, и вы можете полу-чить сразу два сообщения. Похоже, необходимо более конкретно объяснить jQuery, чего мы хотим…
Тест-драйв
дальше� 81
селекторы и методы
div
div div div div
Проблема в том, что мы слишком расплывчато сформулировали правило выбора элементов. Так как же отобрать четыре вложенных области div без вмещающего элемента div? Вспомните, о чем говорилось в главе 1: селек-торы jQuery используют классы и идентификаторы CSS. Вы всегда можете уточнить, с какими элементами должна выполняться операция, назначая этим элементам классы и идентификаторы.
Этот элемент div не должен
реагировать на щелчки мы-шью. Он используется только
для отображения информации.
Âûðàæàéòåñü òî÷íåå
Что лучше использовать для определения элементов div в на-шем примере — только классы CSS, только идентификаторы или их сочетание? Какой способ лучше подойдет и почему?
Все эти элементы div должны ре-агировать на щелчки, так как они используются во взаимодействиях с пользователем.
Мозговой
штурм
82 глава 2
классы элементов
$(".nav").click( function(){
alert("You clicked me!");
});
В CSS классы используются для группировки элементов и назна-чения им общих стилевых атрибутов. Страница может содержать один или несколько элементов, относящихся к одному классу. В jQuery можно использовать селектор классов, чтобы действие методов jQuery распространялось на определенную группу элемен-тов. И в CSS, и в jQuery для обозначения классов используется сим-вол «.», поэтому присвоить класс элементу проще простого.
Íàçíà÷åíèå êëàññîâ
Селекторы клас-сов отбирают все элементы, входящие в заданный класс.
body
html
div
div class="nav" p id="my_blurb"div class="nav"
Древовидная структура DOM для веб-страницы.
Дерево DOM.
.nav { display: block; border: solid #00f 1px; width: 100%;}
Код CSS Код jQuery
дальше� 83
селекторы и методы
Èäåíòèôèêàòîðû ýëåìåíòîâ
Селектор идентификаторов предназначен для выбора одного конкретного элемента страницы. В jQuery, как и в CSS, селекторы идентификаторов обозначаются символом #. Они особенно хорошо подходят для максимально точного определения элемента стра-ницы, а также для определения элементов, заведомо существующих только в одном эк-земпляре (например, заголовка или завершителя страницы).
Класс
Однозначно определяет уникальный элемент страницы
Укажите, для каких целей могут использоваться классы и идентифи-каторы, сделав пометку в соответствующем столбце. Не забывайте, что класс и идентификатор иногда могут делать одно и то же!
Идентификатор
Определяет один или несколько элементов страницы
Может использоваться одним методом JavaScript
для кросс-браузерной идентификации элемента
Может использоваться в CSS для применения стилей
к элементам
Может многократно назначаться одному элементу
Селекторы идентификаторов опре-деляют один конкретный элемент.
$("#my_blurb").slideToggle("slow");#my_blurb { display: block; border: 0px; height: 50%;}
Код jQuery
Кто и что делает?аеааеееееееееееееееее
Код CSS
84 глава 2
решение упражнения
В: Что такое блочный элемент?
О: Блочные элементы отображаются внутри своих родительских элементов как прямоугольные объекты, не выходящие за их границы. Для них определяются свойства блочных полей, ширины и высоты, которые могут задаваться независимо от окружаю-щих элементов.
В: Почему тег <script> размеща-ется в конце страницы перед те-гом </body>? Мне казалось, что он должен находиться в тегах <head> </head>?
О: Да, когда-то это считалось правильным (а кое-кто продолжает так считать). Однако
у такого размещения сценариев есть один недостаток: оно блокирует параллельную загрузку в браузере. В общем случае изо-бражения с разных серверов могут загру-жаться одновременно, но после того как ваш браузер встретит тег <script>, даль-нейшая параллельная загрузка невозможна. Размещение сценариев в конце страницы сокращает время загрузки страницы.
В: Для чего нужны окна сообще-ний JavaScript?
О: Окна сообщений не блещут красо-той, но приносят немалую пользу. По сути функция alert отображает простое окно с текстом, указанным в круглых скобках при ее вызове. Если вы хотите вывести строку текста, заключите ее в кавычки. Чтобы
вывести значение переменной, укажите имя переменной без кавычек. Значения переменных также можно объединять со строками при помощи знака +. Наверняка вы уже встречались с окнами сообщений, даже если не обращали на них особого внимания — например, когда забывали заполнить обязательное поле на форме. В нашем случае окно сообщения исполь-зуется в целях тестирования и отладки. Ко-нечно, существуют и более совершенные средства вывода отладочной информации; они будут представлены в следующих главах книги.
Укажите, для каких целей могут использоваться классы и идентифи-каторы, сделав пометку в соответствующем столбце. Не забывайте, что класс и идентификатор иногда могут делать одно и то же!
Однозначно определяет уникальный элемент страницы
Определяет один или несколько элементов страницы
Может использоваться одним методом JavaScript
для кросс-браузерной идентификации элемента
Может использоваться в CSS для применения стилей
к элементам
Может многократно назначаться одному элементу
Кто и что делает?аеааеееееееееееееееее
решение
Класс Идентификатор
частоЗадаваемые
вопросы
дальше� 85
селекторы и методы
Áåñåäà ó êàìèíà: ñåëåêòîðû CSS è jQuery îáñóæäàþò ñâîè ðàçëè÷èÿ.
Ñåëåêòîð CSS:
Привет, Селектор jQuery. Хорошо, что ты здесь — так окружающие скорее поймут, что своим суще-ствованием ты обязан исключительно мне.
Да уж, стиля мне не занимать — но кто сказал, что я ничего не делаю? Я могу моментально изменить внешний вид многих объектов на странице.
И что же можешь сделать ты, чего не могу я?
Началось, технический жаргон... Что это значит «возвращаешь» элементы?
Но я тоже могу влиять на все выбранные элемен-ты — cкажем, назначить им всем розовый цвет фона. И не забывай, что вся твоя функциональ-ность обеспечивается моими механизмами.
Да, пожалуй, это впечатляет.
Ñåëåêòîð jQuery:
А, да, спасибо... Конечно, моя сила во многом обу-словлена твоими способностями к выбору эле-ментов. Однако я ориентируюсь на поведение, а не на стилевое оформление. Твое дело — про-стое украшение страницы, а благодаря мне вы-полняется серьезная работа.
Не спорю, польза от тебя есть. У тебя своя рабо-та — изменение внешнего вида элементов, а у меня своя — совершенно другая.
Я нахожу элементы и возвращаю их, чтобы метод мог выполнить какую-либо операцию с возвраща-емым набором.
Допустим, кто-то использует меня для выбора всех элементов абзацев на странице. Я отбираю все абзацы и передаю их методу jQuery для даль-нейшей обработки.
Верно, твой механизм селекторов лежит в основе части моих возможностей, но другую часть пре-доставляет JavaScript. Не забудь о слове «запрос» (Query) в моем имени. Я запрашиваю у браузера элемент и передаю его методу jQuery, а метод за-ставляет этот элемент летать по странице или даже раствориться в воздухе.
Да, и ты кое в чем прав — без тебя я бы этого сде-лать не смог.
Беседа у камина
86 глава 2
три уровня
Òðè óðîâíÿ âåá-ñòðàíèöû
Стилевое оформление =
CSS
Структура = HTML
Сценарный код = jQuery (и JavaScript)
Классы и идентификаторы закладывают основу для трех уровней веб-страницы, рассмотрен-ных нами в главе 1: структуры, стилевого оформления и сценарного кода. Селекторы связывают эти уровни, позволяя им взаимодействовать друг с другом. HTML предоставляет «строитель-ный материал» (элементы, атрибуты и т. д.), или структуру веб-страницы. CSS предоставля-ет стилевое оформление, то есть описание представления и размещения этих элементов. JavaScript и jQuery предоставляют сценарный код, управляющий поведением (функциональ-ностью) этих элементов.
Допустим, элементу img, для которого должен выполняться метод slideUp, назначен класс slideshow:
<img class="slideshow" />
.slideshow{
float: left;
height: 100;
}
$(".slideshow").slideUp()
Элементу img назнача-ется класс slideshow.
Таблица стилей за-дает параметры представления и позиционирования класса slideshow с использованием селектора.
Сценарная библиотека jQuery выбирает элемент и задает его поведение.
дальше� 87
селекторы и методы
Измените структуру, стилевое оформление и сценарный код
страницы, чтобы на щелчки реагировали только четыре обла-
сти div. В файле CSS создайте класс CSS (с именем guess_box)
и примените его в тегах html и script. Кажется, один из эле-
ментов div также потерял свой атрибут id. Удастся ли вам опре-
делить отсутствующее значение и вернуть его на место?
<html>
<head>
<title>Jump for Joy</title>
<link href="styles/my_style.css" rel="stylesheet">
</head>
<body>
<div id="header">
<h2>Jump for Joy Sale</h2>
</div>
<div >
<div ><img src="images/jump1.jpg"/></div>
<div <img src="images/jump2.jpg"/></div>
<div ><img src="images/jump3.jpg"/></div>
<div ><img src="images/jump4.jpg"/></div>
</div>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script>
$(document).ready(function() {
$(" ").click(function() {
alert("You clicked me.");
});
});
</script>
</body>
</html>
index.html
div{
float:left;
height:245px;
text-align:left;
border: solid #000 3px;
}
#header{
width:100%;
border: 0px;
height:50px;
}
#main{
background-color: grey;
height: 500px;
}
height 245px;
my_style.css
Возьми в руку карандаш
88 глава 2
решение упражнения
Здесь определяется
класс для четырех
областей div. Зна-
чение height соот-
ветствует высоте
используемых изо-
бражений, так что
вся графика сохра-
няет нормальное
выравнивание.
Всем элементам div, в которых будет скрываться код скид-
ки, назначается класс guess_box. Также измените селек-
тор, чтобы в нем использовался этот класс, и включите его
в файл CSS. Атрибут id пропал у главного элемента div.
З
<html>
<head>
<title>Jump for Joy</title>
<link href="styles/my_style.css" rel="stylesheet">
</head>
<body>
<div id="header">
<h2>Jump for Joy Sale</h2>
</div>
<div >
<div ><img src="images/jump1.jpg"/></div>
<div ><img src="images/jump2.jpg"/></div>
<div ><img src="images/jump3.jpg"/></div>
<div ><img src="images/jump4.jpg"/></div>
</div>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script>
$(document).ready(function() {
$(" ").click(function() {
alert("You clicked me.");
});
});
</script>
</body>
</html>
index.html
div{
float:left;
height:245px;
text-align:left;
border: solid #000 3px;
}
#header{
width:100%;
border: 0px;
height:50px;
}
#main{
background-color: grey;
height: 500px;
}
height 245px;
my_style.css
.guess_box
id="main"
class="guess_box"class="guess_box"
class="guess_box"
class="guess_box"
}
Метод click связыва-ется только с классом guess_box, а не со всеми элементами div.
.guess_box{
Возьми в руку карандаш Решение
дальше� 89
селекторы и методы
Вернемся к списку задач и посмотрим, что же мы выполнили из пожеланий Эмили.
Области должны реагировать на щелчки мышью.
Страница должна состоять из четырех областей. Каждая об-ласть содержит одно изображение.
Нам понадобится сообщение, состоящее из текста («Размер вашей скидки:») и случайного значения (от 5 до 10 процентов).
Когда пользователь щелкает в одной из областей, под изобра-жением в этой области должно появляться сообщение.
Если пользователь щелкает снова, то старое сообщение исче-зает и появляется новое.
Âîçâðàùàåìñÿ ê ñïèñêó
Необходимо создать сообщение и где-то сохранить его для вывода. Как вы думаете, как это лучше сделать?
Проще простого. Мы уже почти на середине списка, да и со следующими пунктами особых трудностей не предвидится. Нужно построить строку из текста и числа. Чего тут сложного?
В общем-то ничего.Однако вывод сообщений для пользователя связан с некоторыми нюансами. Не забывайте, что для разных посетителей сайта могут выводиться раз-ные сообщения.
Мозговой
штурм
90 глава 2
хранение данных
Âûäåëåíèå ïàìÿòè äëÿ õðàíåíèÿ äàííûõ
Следующее требование в нашем списке — вывод текста, который остается неизменным при каждом выполнении сценария. Но помимо этого, необ-ходимо хранить число, которое генерируется в зависимости от случайной величины. С другой стороны, на протяжении работы сценария это число должно каким-то образом сохраняться. Для хранения такой информации при работе с jQuery используются переменные JavaScript.
var pts = 250;
Ключевое слово var
объявляет переменную.
За ключевым словом var указывается имя переменной. Так значение переменной за-
дается в программном коде.
При объявлении переменной интерпретатор JavaScript выделяет блок памяти браузера, в котором будут храниться ваши данные.
pts
Переменной присваи-вается имя, по кото-рому вы будете позд-нее обращаться к ней в своем сценарии.
pts
=250
Значение, сохраня-емое в переменной, указывается после знака равенства.
Теперь, чтобы получить доступ к сохраненным данным, достаточно указать имя переменной.
Если вы захотите больше узнать о переменных JavaScript и мате-матических функциях, найдите книгу М. Моррисона «Изучаем JavaScript» (Питер, 2012)!
дальше� 91
селекторы и методы
var discount = Math.floor((Math.random()*5) + 5);
Следующий фрагмент кода JavaScript создает переменную с именем discount, в которой хранится случайное число от 5 до 10. Напишите код создания переменной discount_msg, содержащей текст сообщения и случайное число. Позаботьтесь о том, чтобы сообщение содержалось в элементе абзаца.
var msg = "High score: <strong>"+pts+"</strong>"
"High score: <strong>"
pts
"</strong>"
Символ «+» использу-ется для конкатенации (объединения) текста, чисел, переменных и т. д.
Теги HTML тоже могут храниться в переменных!
Êîíêàòåíàöèÿ è ñëèÿíèå äàííûõ
В разных сценариях jQuery нам придется сохранять разные типы данных: числа, текст, логические признаки «истина/ложь». Достаточно часто (особенно когда потребуется выводить разные сообщения для пользователей) разметка HTML будет смешиваться с другими данными. Как же переменные объединяются с другими значениями? Посред-ством конкатенации. Допустим, в вашей видеоигре переменная с именем pts использу-ется для хранения рекорда, и вы хотите вывести ее значение.
Нужно объединить три фрагмента:
Текст и фрагменты кода HTML заключа-ются в кавычки.
При обращении к пере-менной указывается ее имя без кавычек.
Получается следующее:
Упражнение
92 глава 2
решение упражнения
<script>
$(document).ready(function() {
$(".guess_box").click( function() {
var discount = Math.floor((Math.random()*5) + 5);
var discount_msg = "<p>Your Discount is "+ discount +"%</p>";
alert(discount);
});
});
</script>
index.html
Математические операции и функция random рассматри-ваются в главе 3.
Итак, теперь у нас есть переменная, в которой хранится объединенное сообщение о скидке. Остается лишь обно-вить фрагмент, заключенный в теги <script>.
Âîçâðàùàåìñÿ ê ïðîãðàììíîìó êîäó…
Мы передаем переменную discount функции alert, чтобы убедиться в том, что она содержит нужный текст.
Создаем новые переменные JavaScript.
var discount = Math.floor((Math.random()*5) + 5);
Следующий фрагмент кода JavaScript создает переменную с именем discount, в которой хранится случайное число от 5 до 10. Напишите код создания переменной discount_msg, содержащей текст сообщения и случайное число. Позаботьтесь о том, чтобы сообщение содержалось в элементе абзаца.
var discount_msg = "<p>Your Discount is "+ discount +"%</p>";
Задание!
дальше� 93
селекторы и методы
$("p").append(" <strong>Like me, for instance.</strong>");
Âñòàâêà ñîîáùåíèÿ
Сообщение готово, но как вывести его на странице под изображением, на котором был сделан щелчок? По сути, речь идет о вставке нового содержимого в страницу. В jQuery предусмотрено несколько способов вставки содержимого в существую-щие элементы. Самые полезные способы будут подробно рассмотрены в главе 4, а пока мы воспользуемся действием append.
jQuery lets me add stuff onto my web page without having to reload it. Like me, for instance.
Если выполнить эту команду в секции сценарного кода, то на странице появится текст, выделенный жирным шрифтом.
Эта команда jQuery приказывает интерпретатору JS присоединить
содержимое, заданное в круглых скобках, ко всем элементам абзацев.
Итоговый код HTML в модели DOM.
Используя то, что вы уже знаете о селекторах, а также только что описанный метод append, напишите код присоединения переменной discount к элементу guess_box.
<p>jQuery lets me add stuff onto my web pagewithout having to reload it.</p>
<p>jQuery lets me add stuff onto my web page without having to reload it.</p> <strong>Like me,for instance.</strong>
Упражнение
94 глава 2
решение упражнения
$(".guess_box").append(discount_msg);
Как видите, включить новое сообщение в веб-страницу совсем несложно!
append — метод jQuery. Методы
используются в jQuery для выпол-
нения различных операций.
частоЗадаваемые
вопросы
В: Существуют ли ограничения для имен классов?
О: Имя класса должно начинаться с символа под-черкивания (_), дефиса (-) или буквы латинского алфавита (a–z), за которыми может следовать любое количество дефисов, символов подчерки-вания, букв или цифр. Правда, есть еще правило: если первым символом является дефис, то вторым символом должна быть буква или символ под-черкивания, а имя должно содержать не менее двух символов.
В: Существуют ли ограничения для имен переменных?
О: Да! Имена переменных не могут начинаться с цифр. Кроме того, они не могут содержать знаки математических операторов (+ * - ^ / ! \), пробелы или знаки препинания. При этом допускается ис-пользование символов подчеркивания. Имена переменных не могут совпадать с ключевыми словами JavaScript (например, window, open, array, string, location), и в них учитыва-ется регистр символов.
В: Сколько классов можно назначить элементу?
О: Согласно стандартам, четко определенного максимума не существует, но в условиях реального использования ограничение составляет около 2000 классов на элемент.
В: Можно ли выбрать все элементы страницы?
О: Да! Для получения всех элементов достаточно передать jQuery селектор “*”.
В: Если я присваиваю элементам класс или идентификатор, не опреде-ляя для него стилевого оформления, повлияет ли это на их внешний вид в браузере?
О: Нет, в браузерах не существует оформления по умолчанию для классов или идентификаторов. Некоторые браузеры используют несколько иную процедуру обработки таких элементов, но наличие класса или идентификатора, к которому не приме-нено оформление CSS, не отразится на внешнем виде элементов.
дальше� 95
селекторы и методы
Âñå îòëè÷íî ðàáîòàåò, íî…Переменная discount генерирует случайное число, а сообщение присоединяется к стра-нице так, как и ожидалось, но мы сталкиваемся с неожиданным побочным эффектом: ин-формация о скидке выводится во всех областях div. Это не совсем то, чего мы добивались. Что же пошло не так?
<script> $(document).ready(function() { $(".guess_box").click( function() { var discount = Math.floor((Math.random()*5) + 5); var discount_msg = "<p>Your Discount is "+discount+"%</p>"; alert(discount_msg); $(".guess_box").append(discount_msg); }); });</script>
Селектор работает на уровне класса,
так что операция распространяется на
все элементы div, принадлежащие классу.
Здесь элемент связывается с методом click, чтобы все элементы класса guess_box ре-
агировали на щелчки мышью.
Сообщение о скидке должно выводиться только в той отдельной области div, на которой щелкает пользователь. Как же выбрать только ту область, в которой был сделан щелчок, и присоединить содержимое discount только к этой области?
Просто для про-верки значения переменной.
Откройте страницу в своем любимом браузере и убедитесь в том, что все работает. Обратите особое внимание на вызов alert — убедитесь в том, что значение перемен-ной discount успешно сохраняется.
При каждом щелчке сообщение о скидке включается
в каждый элемент div, принадлежащий классу guess_box.
Тест-драйв
96 глава 2
в идеальном мире
А как было бы замечательно, если бы в jQuery можно было легко определить эле-мент div, на котором щелкнул пользователь?
Но это, конечно, всего лишь мечты...
дальше� 97
селекторы и методы
Äàéòå ìíå $(this)
В этой главе рассматривались селекторы jQuery и их использование для выбора элементов, с которыми работают методы jQuery. Довольно ча-сто мы хотим предельно конкретно указать, какой элемент требуется выбрать. В подобных ситуациях часто используется простейший селек-тор $(this), обозначающий текущий элемент.
Помните, что смысл конструкции $(this)зависит от контекста. Иначе говоря, смысл $(this) изменяется в зависимости от того, где и как вы используете эту конструкцию. В частности, ее уместно использовать вну-три функции, выполняемой при вызове метода jQuery:
$("#myImg").click( function(){ $(this).slideUp();});
$(this)
$( )
this Ключевое слово «this» обозначает текущий элемент, с которым мы работаем.
Функция, выпол-няемая при вызове метода.
Вызов метода jQuery.Селектор для обраще-ния к элементу.
Метод jQuery будет при-менен только к текущему элементу.
Как и прежде, используем обертку jQuery.
И click, и slideUp являются
методами jQuery. Мето-
ды и функции легко узнать
по круглым скобкам.
Для любознательных
Обращение к текущему элементу (#myImg в данном
случае) внутри функции.
this è $(this)
В JavaScript ключевое слово «this» обозначает элемент DOM, с ко-торым мы работаем в своем коде. Добавление $( ) (в результа-те чего получается $(this)) позволяет нам взаимодействовать с элементом DOM с использованием методов jQuery.
98 глава 2
Тест-драйв
$(this) в действии
Давайте посмотрим, как $(this) поможет справиться с возникшей пробле-мой. Измените программный код так, чтобы в нем использовалась конструкция $(this); ниже соответствующий фрагмент выделен жирным шрифтом.
Сообщение о скидке присоединя-ется только к тому элементу класса guess_box, на котором щелкнул пользователь.
Èñïîëüçîâàíèå $(this)
Откройте страницу в своем любимом браузере и убедитесь в том, что все работает. Обратите особое внимание на вызов alert — убедитесь в том, что значение переменной discount успешно сохраняется. Щелкните несколько раз в разных местах; проверьте правильность вывода случайного числа, присо-единенного к текстовому сообщению.
Задание!
Сообщение о скидке присоединя-ется только к тому элементу класса guess_box, на котором щелкнул пользователь.
<script type="text/javascript">
$(document).ready(function() {
$(".guess_box").click( function() {
var discount = Math.floor((Math.random()*5) + 5);
var discount_msg = "<p>Your Discount is "+ discount +"%</p>";
alert(discount_msg);
$(this).append(discount_msg);
});
});//end doc ready
</script>
index.html
дальше� 99
селекторы и методы
Хороший вопрос!Мы подошли к последнему пункту нашего списка задач.
Области должны реагировать на щелчки мышью.
Страница должна состоять из четырех областей. Каждая область содержит одно изображение.
Нам понадобится сообщение, состоящее из текста («Размер вашей скидки:») и случайного значения (от 5 до 10 процентов).
Когда пользователь щелкает в одной из областей, под изо-бражением в этой области должно появляться сообщение.
Если пользователь щелкает снова, то старое сообщение исчезает и появляется новое.
$(this) прекрасно работает! Но теперь при повторных щелчках на стра-
нице появляются лишние сообщения. Можно ли от них избавиться?
Как вы думаете, как удалить со страницы послед-нее сообщение?
Мозговой
штурм
100 глава 2
удаление элементов
Ñêàòåðòüþ äîðîãà! Ìåòîä remove
Как удалить последнее сообщение и создать новое? Используйте метод remove. Этот метод предназначен для удаления со страницы отдельного элемента или группы элементов. Взгляните на очень простую страницу со списком и кнопкой.
Как может выглядеть селектор, который удалит со страницы только сообщение о скидке?
Слева показано, как страница выглядит в браузере, а справа приведена разметка HTML для ее создания.
1
А это код кнопки, удаляющей все пункты из списка:2
Посмотрите на страницу в браузере и на HTML после выполнения кода jQuery: все пункты списка исчезли, их нет даже в HTML!
3
$("#btnRemove").click(function(){
$("li").remove();
});
 áðàóçåðå
 áðàóçåðå
 ðàçìåòêå HTML
 ðàçìåòêå HTML
<div>My To Do List</div>
<ol>
<li>Learn jQuery</li>
<li>Ask the Boss for a raise</li>
<li>Tweet about my raise</li>
</ol>
<button id="btnRemove">
<div>My To Do List</div>
<ol>
</ol>
<button id="btnRemove">
remove — еще один метод jQuery. Мето-ды jQuery определяют действия, выполняе-мые с веб-страницей.
Мозговой
штурм
дальше� 101
селекторы и методы
$("div div div div pp")$("div p")
Ñåëåêòîðû ïîòîìêîâ
Селекторы потомков — еще одна разновидность селекторов, которая может использо-ваться в jQuery. Оказывается, они идеально подходят для нашей ситуации. Селекторы потомков позволяют определять отношения между элементами: вы можете выбирать родительские, дочерние или сестринские (одноранговые) элементы.
Справа указывается селектор потомка.
Слева указыва-ется селектор родителя.
Имена родителя и потомка разде-ляются пробелом.
А так выбира-ется «потомок потомка».
$("div div")
$("div div img")
$("div p#my_blurb")
$("div p")
Объединение селекторов классов и иден-тификаторов с селекторами потомков позволяет очень точно определить выби-раемые элементы, что особенно важно при работе со сложными веб-страницами.
Выбор всех элемен-тов p, родителями которых являются элементы div.
Выбор всех элементов img, которые являются потомками потомков элементов div.
Селектор возвраща-ет все элементы div, родителем которых является элемент div. body
html
div
div p id="my_blurb"div
p img
(«Внучатые» элементы?)
Возьми в руку карандашНапишите команду, которая будет удалять последнее сообщение в модели DOM из нашего примера с использованием селектора потомков.
102 глава 2
решение упражнения
Начните с селектора классов .guess_box, за ним укажите селектор
потомков p для обращения к добавленному элементу абзаца. Затем
вызовите метод remove, чтобы удалить из страницы все элементы p,
родитель которых принадлежит к классу guess_box.
$(".guess_box p").remove();
Итак, теперь я могу присоединять и удалять фрагменты страницы по своему
усмотрению. Важно ли, где и когда это происходит?
Да, порядок добавления и удаления элементов важен.
Ведь вы не сможете удалить элемент до того, как он будет добавлен, — и было бы бессмысленно удалять элемент сразу же после его добавления, верно?
Если пользователь щелкает во второй раз, мы удаляем присоединенный элемент аб-заца, после чего присоединяем новый элемент абзаца.
Когда пользователь щелкает на этом элементе, к нему присоединяется эле-мент абзаца.
p
body
html
div id="header"
div id="main"
h2div class=
"guess_box"div class="guess_box"
div class="guess_box"
div class=
"guess_box"
img img img img
p
Возьми в руку карандаш Решение
дальше� 103
селекторы и методы
Решите, где должна находиться команда remove. Запишите ее в одной
из строк 1, 2 или 3 и объясните, почему разместили ее именно в этой
строке. Подумайте, когда должен удаляться абзац, и методом исключе-
ния выберите правильное место для выполнения этой операции.
Почему я считаю, что команда должна находиться именно здесь:
<script>
$(document).ready(function() {
$(".guess_box").click( function() {
var discount = Math.floor((Math.random()*5) + 5);
var discount_msg = "<p>Your Discount is "+ discount +"%</p>";
alert(discount_msg);
$(this).append(discount_msg);
});
});
</script>
1.
2.
3.
index.html
Возьми в руку карандаш
104 глава 2
решение упражнения
Команда remove не может находиться в строке 1, потому что эта строка находится за пределами функции click класса guess_box. Она также не может находиться в строке 3, потому что в этом случае она будет удалять только что присоединенный фрагмент. Последнее сообщение о скидке должно удаляться перед генерированием нового, поэтому мы размещаем remove в первой строке блока кода (в фигурных скобках) функции click класса guess_box.
Очень важно, чтобы методы jQuery вызывались в правиль-ном порядке и в правильный момент.
Причем это особенно важно тогда, когда вы выводите важную информацию для своих посетителей, а потом удаляете ее снова. Мы еще вернемся к теме последовательности и свое-временности применения эффектов в главе 5.
Решите, где должна находиться команда remove. Запишите ее в одной
из строк 1, 2 или 3 и объясните, почему разместили ее именно в этой
строке. Подумайте, когда должен удаляться абзац, и методом исключе-
ния выберите правильное место для выполнения этой операции.
Почему я считаю, что команда должна находиться именно здесь:
<script>
$(document).ready(function() {
$(".guess_box").click( function() {
var discount = Math.floor((Math.random()*5) + 5);
var discount_msg = "<p>Your Discount is "+ discount +"%</p>";
alert(discount_msg);
$(this).append(discount_msg);
});
});
</script>
1.
2.
3.
index.html
$(".guess_box p").remove();
Возьми в руку карандаш Решение
Будьте осторожны!
дальше� 105
селекторы и методы
В: Иногда после вызова метода remove элементы, удаленные из разметки, остаются на странице. Почему это происходит?
О: Часто при использовании команды получения исходного кода страницы браузер обращается к серверу с новым вы-зовом. Инспекторы DOM (например, Chrome Developer Tools или Firebug для Firefox) покажут вам содержимое DOM для текущего состояния страницы.
В: Что делают методы Math.floor и Math.random?
О: Метод floor округляет число вниз до ближайшего целого и возвращает результат. Метод random возвра-щает случайное число от 0 до 1. При умножении его на другое число мы получаем случайное число в интервале от 0 до числа-множителя.
В: Откуда взялось ключевое слово this?
О: Во многих объектно-ориентированных языках ключевым словом this (или self) в методах экземпляров обознача-ется объект, для которого был вызван метод, выполняемый в настоящий момент.
В: Значит, я могу выводить сообщение о скид-ке тогда, когда пользователь щелкает на одном из изображений, и удалять ее при щелчке на другом изображении. Но ведь для реально-го приложения этого было бы недостаточно, верно?
О: Вы абсолютно правы. Это всего лишь первая часть головоломки. Этот код должен передать информацию о предоставленной скидке в тот момент, когда пользователь переходит к оформлению заказа. Чтобы скидка была учтена при расчете, ее необходимо передать серверу для обработки. Такая функциональность более подробно рассматривается в главах 8–10.
частоЗадаваемые
вопросы
106 глава 2
тест-драйв
Включите только что написанную строку кода в файл index.html. Затем откройте страницу в своем любимом браузере и убедитесь в том, что все работает. Несколько раз щелкните на изображении и проверьте, что сообщение о скидке успешно выводится, а старое сообщение удаляется перед присоединением нового кода.
Тест-драйв
дальше� 107
селекторы и методы
Âàøà î÷åðåäü ïðûãàòü îò ðàäîñòè
Поздравляем! Вы справились со всеми требованиями, и рекламная акция теперь заработает.
Области должны реагировать на щелчки мышью.
Страница должна состоять из четырех областей. Каждая область содержит одно изображение.
Нам понадобится сообщение, состоящее из текста («Размер вашей скидки:») и случайного значения (от 5 до 10 процентов).
Когда пользователь щелкает в одной из областей, под изо-бражением в этой области должно появляться сообщение.
Если пользователь щелкает снова, то старое сообщение исчезает и появляется новое.
От: ЭмилиТема: Re: Рекламная акция «Прыгаем от радости!»
Спасибо за то, что ты сделал для меня! Мой сайт стал гораздо лучше.
Надеюсь, посетители будут в таком же восторге от моих фотографий,
как я — от новой страницы!
--Эмили
> PS. Прилагаю свой автопортрет — так я выглядела, когда увидела новую
веб-страницу... Надеюсь, не нужно объяснять, что я делаю?
108 глава 2
ваш инструментарий jquery
Âàø èíñòðóìåíòàðèé jQuery
Глава 2 осталась позади, а ваш творче-ский инструментарий дополнился основ-ными принципами работы с селекторами и некоторыми методами jQuery.
$(this)
Выбирает «текущий» элемент.
Смысл $(this) изменяется в зависи-
мости от того, где находится эта
конструкция.
Селекторы
$(this) — выбирает текущий элемент.
$("div") — выбирает все элементы div
на странице.
$("div p") — выбирает все элементы p,
вложенные непосредственно в элемен-
ты div.
$(".my_class") — выбирает все элемен-
ты класса my_class.
$("div.my_class") — выбирает толь-
ко те элементы, которым назначен
класс my_class. (Разные типы эле-
ментов могут относиться к одному
классу.)
$("#my_id") — выбирает элемент
с идентификатором my_id.
Методы jQuery
Метод jQuery представляет собой
фрагмент кода, определенный в библи-
отеке jQuery и предназначенный для
многократного использования. Методы
используются для выполнения раз-
личных операций в jQuery и JavaScript.
Считайте, что метод — своего рода
команда, выполняющая некоторые
операции с веб-страницей.
.append — вставляет заданное содер-
жимое в DOM. Данные присоединяют-
ся к элементу, для которого вызыва-
ется метод.
.remove — удаляет элемент из DOM.
ГЛА
ВА 2
Нет, я непременно докопаюсь до сути...
События и функции jQuery3
Страница в центре событий
jQuery позволяет легко включить в любую веб-страницу поддержку действий и интерактивности. В этой главе вы узнаете, как заставить вашу страницу реаги-ровать на действия, выполняемые пользователем. Возмож-ность выполнения кода в ответ на действия пользователя поднимает сайт на совершенно новый уровень. Также в этой главе рассказано, как создавать функции, чтобы однократно написанный код можно было использовать много раз.
110 глава 3
дела финансовые
Эмили довольна вашей работой для рекламной акции «Прыгаем от радости», но после встречи с бухгалтером она хочет внести на сайте некоторые изменения.
Íè ìèíóòû ïîêîÿ
От: ЭмилиТема: RE: Прыгаем от радости
Привет,
Ты отлично справился с поддержкой нашей рекламной акции! Я встречалась
с нашим бухгалтером, и мы обсудили некоторые показатели успеха нашей
рекламной акции.
Бухгалтер предложил внести в приложение некоторые изменения, которые
должны повысить уровень продаж.
Посетители по-прежнему получают четыре изображения для выбора скидки.
Однако на этот раз величина скидки остается постоянной. Бухгалтер рекомен-
дует установить величину в 20% от объема заказа, такая высокая скидка будет
для них более привлекательной.
Посетитель получает только одну возможность найти код скидки, который при
каждом посещении скрывается под случайно выбранным изображением. Если
посетитель находит код скидки, щелкнув на изображении, то код появляется на
экране. В противном случае приложение показывает, под каким изображением
была спрятана скидка.
Удастся ли тебе справиться с этой задачей так же хорошо, как и с первой?
--Эмили Сондерсjumpforjoyphotos.hg
Эмили приложила фотографии своего бухгалтера — тот явно не собирается прыгать от радости. Может, после внесения изменений на сайте дело пойдет на лад?
дальше � 111
события и функции jquery
 ñëîâàõ áóõãàëòåðà åñòü ðåçîí...
Если скидка будет скрываться только под одним изображением, Эмили не придется возиться с лишними кодами, а посетители все равно будут взаимодействовать с сайтом. Похоже, все эти новые возможности нужны только для одного: заставить посетителей побольше щелкать...
Щелк!Щелк!
Щелк!Щелк!Щелк!Щелк!
Щелк!Щелк!Щелк!Щелк!
Требования:
Пришло время создавать новый список требований. Вы уже знаете, что
делать: просмотрите сообщение Эмили и выберите все новые возмож-
ности приложения, которые она хочет видеть на своем сайте. Опишите
простыми словами, как должно работать новое решение.
Возьми в руку карандаш
112 глава 3
решение упражнения
Вы знаете, как включить в страницу функцию click. Но как убедиться в том, что посетитель использует ее только один раз?В предыдущих главах вы узнали, как организовать выполнение кода при вызове click. Нельзя ли использовать эту информацию в реализации нового решения?
Êàê íàøå ðåøåíèå ðàáîòàåò ñåé÷àñ Êàê îíî äîëæíî ðàáîòàòü
Щелкай на здоровье! Чем больше — тем лучше!
Требования:
У тебя только одна попытка!
• После загрузки страницы посетителю предоставляется только одна возмож-ность найти скидку. Следовательно, если первая попытка оказалась неудачной, то дальнейшие щелчки необходимо заблокировать.
• После того как посетитель выбрал изображение и щелкнул на нем, следует со-общить о результате. Если изображение было выбрано правильно, нужно вывести величину скидки.
• Скидка должна скрываться только в одном из четырех изображений, и при каждой загрузке страницы изображения должны располагаться в случайном порядке.
• Вместо случайной скидки будет использоваться постоянная скидка 20 %. Таким образом, вместо процента в сообщении следует вывести код скидки.
Возьми в руку карандаш Решение Пришло время создавать новый список требований. Вы уже знаете, что
делать: просмотрите сообщение Эмили и выберите все новые возмож-
ности приложения, которые она хочет видеть на своем сайте. Опишите
простыми словами, как должно работать новое решение.
Мозговой
штурм
дальше � 113
события и функции jquery
Submit
Submit
$("#btnSubmit").click( function(){
// Код jQuery!
$("div").toggle();
});
Ðåàêöèÿ íà ñîáûòèÿ
Работа приложения «Прыгаем от радости» основана на щелчках мышью. В jQuery и JavaScript щелчок называется событием (существует много других событий, но нас пока интересуют только щелчки). Механизм событий позволяет вам выполнять код, когда со страницей что-то происходит (например, пользователь щелкает на кнопке). Выполняемый код оформлен в виде функции — а как говорилось ранее, функции делают код jQuery более эффективным и пригодным для повторного использования. Вскоре функции будут рассмотрены более подробно, а пока давайте посмотрим, как же на са-мом деле работает событие click.
С кнопкой HTML проис-ходит событие click.
Кнопка HTML
Слушатель (обработчик) Слушатель (обработчик) события обнаруживает события обнаруживает его и передает...его и передает...
Обратите внимание на до-полнительный этап, которого не было в главе 1.
…и выполняет код, изме-няющий страницу.
...интерпретатору JavaScript, который определяет, что должно происходить при каж-дом событии…
Щелк!Щелк!
А что это за «слушатель со-бытия»? Раньше его не было.
Что именно он делает?
Хороший вопрос.Слушатели событий являются частью модели DOM. Их мож-но включить в любую страни-цу, чтобы операции со страни-цей могли выполняться и без участия пользователя, щелка-ющего на ссылках и кнопках. Давайте разберемся поглубже.
114 глава 3
свет, камера, события
При помощи слушателей событий браузер получает информацию о том, что поль-зователь сделал на странице, и указывает интерпретатору JavaScript, должен ли тот что-то предпринять по этому поводу.
jQuery предоставляет очень простые механизмы связывания слушателей событий с любым элементом страницы, так что пользователям не приходится долго кликать по ссылкам и кнопкам!
Çà êóëèñàìè ñëóøàòåëÿ ñîáûòèé
Что вы видите в браузере
Я слышу щелчок.
Я должен вывести окно сообщения!
Пользователь щелкнул на элементе.1
Интерпретатор JavaScript
Слушатель события, связанный с элементом, «слышит» событие click и сообщает интерпретато-ру JavaScript, какой код связан с этим событием.
2
Интерпретатор JavaScript выполняет функцию, задан-ную в слушателе события.
3
Пользователь видит, как на странице что-то про-исходит.
4
Слушатель события
$("#showMessage").click(function() {
alert('You Clicked Me!');
});
Элемент с иден-тификатором showMessage.
Добавляется событие click.
Выполняется этот код.
Щелк!Щелк!
За
сценой
дальше � 115
события и функции jquery
Ñâÿçûâàíèå ñîáûòèÿ
Добавление события к элементу называется связыванием события с элементом. При этом слушатель события узнает, что он должен сооб-щить интерпретатору JavaScript, какую функцию тот должен вызвать.
Есть два способа связывания событий с элементами.
Способ 1 — всего лишь сокращенная форма способа 2, но он может использоваться только в том случае, если элементы DOM уже суще-ствуют.
В jQuery много таких сокращенных вариантов записи, которые упроща-ют программный код. Они существуют исключительно для удобства — однако у них есть свои ограничения. Способ 2 следует использовать для добавления событий к новым элементам DOM, созданным в вашем коде
(например, когда на странице создается новое изображение, реагирующее на щелчки, или в спи-сок включается новая строка, с которой должен взаимодействовать пользователь).
Этот способ используется для связывания событий с элементами при загрузке страницы. Такая форма записи часто называется «сокращенной».
Этот способ работает так же, как и предыдущий, но он также может использоваться для добавле-ния событий к элементам, включенным в стра-ницу после ее загрузки (например, в результате создания новых элементов DOM).
Оба способа добавляют слуша-теля события click к элементу с идентификатором myElement.
Ñïîñîá 1
Ñïîñîá 2
$("#myElement").click( function() {
alert($(this).text());
});
$("#myElement").bind('click', function() {
alert($(this).text());
});
Будьте осторожны!
116 глава 3
как появляются события
Ñðàáàòûâàíèå ñîáûòèé
События могут срабатывать при выполнении разно-образных операций со страницей. Более того, опе-рации, выполняемые с самим браузером, тоже могут стать источниками событий!
click mousedown mouseout toggledblclick mouseenter mouseoverfocusin mouseleave mouseup
focusout mousemovehover
События мышиkeydownkeypress
keyup
События клавиатуры
События форм
blurchangefocusselectsubmit
События браузера
errorresizescroll
Загрузкадокумента
loadready
unload
События
События
дальше � 117
события и функции jquery
function () { [блок кода, в котором что-то делается]}
Селектор + Событие + Функция = Сложное взаимодействие
В: А что это за функции в собы-тиях?
О: Они называются обработчика-ми. Функция-обработчик выполняется при каждом срабатывании события. Функции будут более подробно рас-смотрены позднее в этой главе.
В: Где можно узнать о разных ви-дах событий?
О: На сайте jquery.com, в разделе «Documentation → Events».
В: Сколько существует разных ка-тегорий событий?
О: В jQuery события делятся на пять категорий: события браузера, события загрузки документа, события форм, со-бытия клавиатуры и события мыши.
В: А сколько вообще существует разных событий?
О: Около 30 разных типов во всех категориях.
В: Что может привести к срабаты-ванию события на странице?
О: Большинство типов событий сра-батывает от операций с устройствами ввода (клавиатура, мышь). Тем не ме-нее браузер, документ страницы, код jQuery и даже форма HTML на странице тоже могут быть источниками событий.
Ñîáûòèå ñðàáîòàëî
Âûïîëíÿåòñÿ ôóíêöèÿ
Интерпретатор JavaScript
Слушатель события
частоЗадаваемые
вопросы
118 глава 3
откровенно о событиях
HeadFirst: Добрый вечер, Событие, мы очень рады встрече.
Событие: Да, и я тоже.
HeadFirst: Так кто же вы? Что собой пред-ставляет настоящее Событие?
Событие: Я — объект, помогающий людям взаимодействовать с веб-страницей. В наши дни я уже твердо стою на ногах, но до появ-ления jQuery мое существование было... как бы это выразиться... немного рассеянным.
HeadFirst: Как интересно. Мы еще вернемся к этой теме, но почему вы говорите о рассеян-ности? Откуда вы вообще появились?
Событие: Это долгая история. В середи-не 1990-х годов фирма Netscape выпустила Navigator 2.0. Какие были времена... Моя модель тогда была очень простой. DOM, JavaScript и я — все мы только-только появи-лись. Существовал стандарт W3C, в котором говорилось, как браузеры должны реализо-вать нас!
HeadFirst: Но это было давно. С тех пор вы сильно изменились.
Событие: Да, все мы изменились. Попутно мы даже ввязались в «войну браузеров» между Microsoft Internet Explorer и Netscape. Обе компании пытались обойти друг друга при помощи всяких классных штучек, которые не входили в стандарт, но поддерживались только в браузере этой компании. В конеч-ном итоге победа досталась Microsoft.
HeadFirst: Похоже, непростое было время.
Событие: Да, но сейчас дела налаживаются. В 1997 году Netscape и Microsoft выпустили
версии 4.0 своих браузеров. В них было мно-го новых событий, а наши возможности по работе со страницей заметно расширились. События тогда пользовались уважением.
HeadFirst: И что произошло?
Событие: Ситуация вышла из-под контроля. Браузер Netscape был преобразован в проект с открытым кодом и позднее превратился в Mozilla Firefox. Но какое-то время браузер Netscape продолжал существовать, причем в нем и в Internet Explorer использовались разные модели событий. Многие решения работали только в одном браузере, а это силь-но раздражало пользователей, заходивших на сайт в другом браузере. В конечном итоге Netscape не стало, но на сцене появилось не-сколько новых браузеров.
HeadFirst: Тогда почему вы говорите, что дела налаживаются?
Событие: Полной совместимости между браузерами по-прежнему нет. Набор собы-тий, поддерживаемых Internet Explorer, от-личается от наборов событий Firefox, Google Chrome, Apple Safari и Opera. Однако ситу-ация меняется к лучшему с выходом каждой новой версии. Браузеры постепенно начи-нают лучше соответствовать стандартам. Но самое замечательное, что jQuery решает эти проблемы за веб-разработчика.
HeadFirst: Правда? Вот здорово! А как? И что это за объект, которым, как вы говорите, вы являетесь?
Событие: jQuery выбирает способ обработ-ки событий в зависимости от того, какой браузер используется посетителем ваших
Интервью недели:Чем так замечательны события?
откровенно
о событиях
дальше � 119
события и функции jquery
сайтов. А что касается объекта, то здесь нет ничего сложного. В сущности, объект — это всего лишь переменные и функции, объеди-ненные в одну структуру.
HeadFirst: И где можно побольше узнать об этих переменных и функциях?
Событие: Вы найдете информацию обо мне в официальной документации jQuery:http://api.jquery.com/category/events/event-object/.
HeadFirst: Спасибо! Непременно почитаю. А что нужно сделать, чтобы использовать вас на странице?
Событие: Для начала меня нужно с чем-то связать — ведь слушатель событий должен знать, что на меня следует обращать вни-мание. Затем какое-то условие должно при-водить к моему срабатыванию, и тогда при возникновении события будет выполняться нужный код.
HeadFirst: Хорошо, но как узнать, какой именно код должен выполняться?
Событие: Этот код определяется при моем связывании с элементом. При этом можно задать практически любой набор операций — поэтому события и считаются такими полез-ными. Кроме того, меня можно отсоединить от элемента. Когда это происходит, слуша-тель перестает обнаруживать события для этого элемента, и тот код, который должен выполняться при моем срабатывании, вы-полняться уже не будет.
HeadFirst: Беседа получилась очень инте-ресной, но наше время на исходе. Где я могу подробнее узнать о вас и о типах событий, которые могут происходить со страницами?
Событие: Уже упоминавшаяся ссылка объ-ясняет, как работает объект. Дополнитель-ную информацию обо мне и о разных типах событий можно найти в разделе докумен-тации на сайте jQuery. Спасибо за пригла-шение!
HeadFirst: И вам спасибо, что пришли. До встреч в программном коде!
Функции и переменные более подробно рассматриваются в этой главе.
Кроме того, в следующих главах будут опи-саны другие аспекты программирования на JavaScript.
Р А СС Л А Б Ь Т Е С Ь
120 глава 3
довольно событий
$("#myElement").bind ('focus', function() {
alert("I've got focus");
});
$("#myElement").click(function(){
alert('You clicked me.');
});
$("#myElement").unbind();
$("#myElement").bind ('click', function() {
alert($(this).text());
});
$("#myElement").unbind('click');
Óäàëåíèå ñîáûòèé
Наряду со связыванием событий с элементами также часто возникает необходимость удаления событий из элементов — например, когда вы не хотите, чтобы пользователи могли повторно щелкнуть на форме или же какая-либо операция со страницей должна выполняться только один раз. Именно такая ситуация встретилась нам в новых требо-ваниях рекламной акции «Прыгаем от радости».
После связывания события с элементом мы можем удалить это событие из элементов, так чтобы оно больше не вызывалось.
Код, который выполняется при щелчке на myElement:
К элементу с иденти-фикатором myElement добавляется слушатель события click.
Событие click отсоединяется от myElement.
Команда unbind приказывает браузеру прекратить прослу-шивать заданное событие конкретного элемента.
К элементу с иденти-фикатором myElement добавляется слушатель события focus.
К элементу с иден-тификатором myElement добав-ляется слушатель события click.
Браузер переста-ет прослушивать события элемента myElement.
Äëÿ óäàëåíèÿ îäíîãî ñîáûòèÿ:
Äëÿ óäàëåíèÿ âñåõ ñîáûòèé:
дальше � 121
события и функции jquery
Итак, слушатель события работает в браузере,присоединяется к элементам, ждет возникновения событий
и приказывает интерпретатору JavaScript что-то сделать при обнаружении события, верно?
Да! Именно так.Посмотрим, как события помогут нам в реализации первого требования.
Не разрешайте пользователю
повторный поиск скидки!
Используя то, что вы уже знаете о $(this), и то, что вы узнали
о событиях, измените код из предыдущей главы — включите в него
команду удаления события click из областей div.
$(".guess_box").click( function() {
$(".guess_box p").remove();
var my_num = Math.floor((Math.random()*5) + 5);
var discount = "<p>Your Discount is "+my_num+"%</p>";
$(this).append(discount);
});
index.html
• После загрузки страницы посетителю предоставляется
только одна возможность найти скидку. Следовательно,
если первая попытка оказалась неудачной, то дальнейшие
щелчки необходимо заблокировать.
Возьми в руку карандаш
122 глава 3
решение упражнения
Измените файл index.html и сохраните его. Пощелкайте на странице и убедитесь в том, что она работает именно так, как нужно.
Используя то, что вы уже знаете о $(this), и то, что вы узна-
ли о событиях, измените код из предыдущей главы — включите
в него команду удаления события click из областей div.
$(".guess_box").click( function() {
$(".guess_box p").remove();
var my_num = Math.floor((Math.random()*5) + 5);
var discount = "<p>Your Discount is "+my_num+"%</p>";
$(this).append(discount);
});
index.html
$(this).unbind(″click″);
Приказываем браузеру остано-
вить прослушивание событий
из текущего элемента.
Возьми в руку карандаш Решение
Тест-драйв
дальше � 123
события и функции jquery
Верно, слушатель события click удаляет-ся не из всех областей.Событие click удаляется только из той области div, на которой был сделан щелчок. На других областях по-прежнему можно щелкать. Как бы удалить слуша-теля события click из всех остальных элементов…
Как бы вы удалили событие click из всех областей после того, как посетитель щелкнет на одной области? Нужно ли для этого перебирать все элементы один за другим?
Наверное, то же, что и у меня. А это совсем не то, о чем говорится
в требованиях...
А вы пробовали пощелкать А вы пробовали пощелкать на странице во время пробно-на странице во время пробно-
го запуска? И что произошло?го запуска? И что произошло?
Мозговой
штурм
124 глава 3
а теперь повторите!
Ïåðåáîð ýëåìåíòîâ
Нередко бывает нужно выполнить некоторую операцию с каждым элементом, входящим в группу.
К счастью, jQuery предоставляет возможность циклического перебора группы элементов, определяемой заданным селек-тором. Проще говоря, вы последовательно, один за одним, перебираете входящие в группу элементы и выполняете не-которую операцию с текущим элементом.
$(".nav_item").each(function(){
$(this).hide();
});
Перебор всех элементов, соответ-
ствующих заданному селектору.Выполняемаяфункция-обработчик
Код выполняется для каждого элемента, соответствующего селектору.
Селектор jQuery.
Итератор .each берет группу эле-
ментов и последовательно выполняет
операцию с каждым элементом группы.
Мы еще вернемся к этой теме,особенно в следующей главе...
Перебор будет более подробно рассмотрен позднее в книге.
дальше � 125
события и функции jquery
Напишите код, использующий перебор для удаления слушателя события
click из всех областей div, реагирующих на щелчки в странице «Прыгаем
от радости». Внимательно прочитайте свой код и проверьте — может,
какие-то из его фрагментов стали лишними?
В: Могу ли я инициировать события в своем коде?
О: Да! Этот прием используется относительно часто — например, при отправке форм для проверки данных или закрытии модальных временных окон.
В: И как это делается?
О: События инициируются методом .trigger в сочета-нии с селектором — например, $("button:first").trigger('click'); или $("form").trigger('submit');.
В: Могу ли я работать с событиями в веб-странице без ис-пользования jQuery?
О: Да, можете. jQuery всего лишь упрощает связывание событий с элементами, потому что библиотека обеспечивает межбраузерную совместимость и использует для связывания событий с элементами простые, легко запоминающиеся функции.
В: Как работает .each?
О:.each использует селектор, от которого исходит вызов, и создает массив элементов, соответствующих данному селектору. Затем в цикле происходит последовательный перебор элементов массива. Не беспокойтесь, вскоре массивы и циклы будут рассмо-трены более подробно!
В: Итак, я могу создавать элементы средствами jQuery после загрузки страницы. Могут ли эти элементы получать события?
О: Да, могут. После того как элемент будет создан, вы можете воспользоваться методом.bind для связывания его со слуша-телем событий. Кроме того, если вам заранее известно, что ваш элемент будет вести себя как другие, уже созданные элементы, вы можете воспользоваться методом .live. Это приведет к тому, что обработчик события будет связываться со всеми элементами, соответствующими текущему селектору, сейчас и в будущем. Это решение подходит даже для элементов, которые еще не были включены в DOM.
$(".guess_box").click( function() {
$(".guess_box p").remove();
var my_num = Math.floor((Math.random()*5) + 5);
var discount = "<p>Your Discount is "+my_num+"%</p>";
$(this).append(discount);
$(this).unbind('click');
});
index.html
частоЗадаваемые
вопросы
Возьми в руку карандаш
126 глава 3
решение упражнения
$(".guess_box").click( function(){
$(".guess_box p").remove();
var my_num = Math.floor((Math.random()*5) + 5);
var discount = "<p>Your Discount is "+my_num+"%</p>"
$(this).append(discount);
$(".guess_box").each( function(){
$(this).unbind('click');
});
});
index.html
Перебираем элементы
.guess_box и удаляем из них
событие click.
Вызов метода .each для класса .guess_box перебирает все эле-
менты этого класса, чтобы вы могли последовательно отсоединить
метод click от каждого элемента. Команда с вызовом .remove стала
лишней; так как посетители всего равно смогут щелкнуть всего один
раз, удалять старое сообщение не нужно.Так как пользователям
разрешается щелкать
только один раз, удалять
старое сообщение уже не-
обязательно!
Стоп!Вы не находите, что в файле
HTML стало слишком много сце-нарного кода? Прежде чем дви-
гаться дальше, хорошо бы придать ему стройности...
Возьми в руку карандаш Решение
дальше � 127
события и функции jquery
Хорошая мысль. Вообще-то существует не-сколько причин для хранения кода jQuery в отдельном файле.
Вы уже знаете, как включить в HTML файлы CSS и библиотеку jQuery. Включение отдельного файла, содержащего ваш сценарный код JavaScript/jQuery, происходит практически так же!
В корневом веб-каталоге уже должна существовать папка scripts (где вы разместили библиотеку jQuery).
<script src="scripts/my_scripts.js"></script>
Так давайте создадим файл сценариев отдельно от файла HTML? Мы уже делали это с CSS...
Файл можно включать в разные страницы (повторное использование кода).
1
Страница будет загружаться быстрее.2
Код HTML станет более стройным и удобочитаемым.3
В своем любимом текстовом редакторе создайте файл с именем my_scripts.js и сохраните его в папке scripts.
1
Создайте ссылку на файл в странице HTML. Для этого перед закры-вающим тегом </body> размещается следующая строка:
3
Перенесите весь код JavaScript и jQuery из файла index.html в новый файл. Переносить теги <script> и </script> необязательно.
2
Упражнение
128 глава 3
решение упражнения
Теперь этот файл можно включать во все
файлы HTML, входящие в проект, — и все
они смогут пользоваться вашим кодом
jQuery. Вам уже не придется повторять
этот код в каждом файле.
Вы уже знаете, как включить в HTML файлы CSS и библиотеку jQuery. Включение отдельного файла, содержащего ваш сценарный код JavaScript/jQuery, происходит практически так же!
В своем любимом текстовом редакторе создайте файл с именем my_scripts.js и сохраните его в папке scripts.
1
Перенесите весь код JavaScript и jQuery из файла index.html в новый файл. Переносить теги <script> и </script> необязательно.
2
$(document).ready(function() {
$(".guess_box").click( function() {
var my_num = Math.floor((Math.random()*5) + 5);
var discount = "<p>Your Discount is "+my_num+"%</p>";
$(this).append(discount);
$(".guess_box").each( function(){
$(this).unbind('click');
});
});
});
my_scripts.js
дальше � 129
события и функции jquery
<!DOCTYPE html>
<html>
<head>
<title>Jump for Joy</title>
<link href="styles/styles.css" rel="stylesheet">
</head>
<body>
<div id="header">
<h2>Jump for Joy Sale</h2>
</div>
<div id="main ">
<div class="guess_box"><img src="images/jump1.jpg"/></div>
<div class="guess_box"><img src="images/jump2.jpg"/></div>
<div class="guess_box"><img src="images/jump3.jpg"/></div>
<div class="guess_box"><img src="images/jump4.jpg"/></div>
</div>
<script src="scripts/jquery.1.6.2.min.js"></script>
<script src="scripts/my_scripts.js"></script>
</body>
<html>
index.html
Да, это уже лучше.Сделано красиво и аккуратно.
Проходите...
Создайте ссылку на файл в странице HTML. Для этого перед закры-вающим тегом </body> размещается следующая строка:
3
130 глава 3
так гораздо лучше
Ñòðóêòóðà ïðîåêòà
Мы только что внесли важные изменения в структуру файлов проекта. Давайте посмотрим, что же получилось в итоге.
В: Почему наш файл имеет рас-ширение .js?
О: Потому что библиотека jQuery написана на JavaScript и весь на-писанный для нее код должен вклю-чаться по правилам кода JavaScript.
В: Как отделение сценарного кода ускоряет загрузку страницы?
О: Если ваш файл .js включен в несколько файлов HTML, то брау-зер запросит его только один раз. Полученный файл сохраняется в кэше браузера, чтобы ему не прихо-дилось заново обращаться к серверу для каждой страницы HTML, содер-жащей ссылку на ваш файл.
В: Почему теги <script>и </script> необязательны в файле my_scripts.js?
О: Потому что это теги HTML. Так как наш код уже включается в страницу как файл JavaScript, брау-зер уже знает тип его содержимого.
images
scripts
styles
root
jump1.jpg
jump2.jpg
jump3.jpg
jump4.jpg
jquery-1.6.2.min.js
my_scripts.js
my_style.css
index.html
частоЗадаваемые
вопросы
дальше � 131
события и функции jquery
jquery-1.6.2.min.js
".guess_box"
class="guess_box"
class="guess_box"
script
});
</div>
this
<body>
my_num
<head>
"
<!DOCTYPE html>
<html>
<title>Jump for Joy</title>
<link href="styles/styles.css" rel="stylesheet">
</head>
<div id="header">
<h2>Jump for Joy Sale</h2>
<div id="main">
<div ><img src="images/jump1.jpg"/></div>
<div class="guess_box"><img src="images/jump2.jpg"/></div>
<div class="guess_box"><img src="images/jump3.jpg"/></div>
<div ><img src="images/jump4.jpg"/></div>
</div>
<script src="scripts/ "></script>
< src="scripts/my_scripts.js"></script>
</body>
<html>
$(document).ready(function() {
$( ).click( function() {
var = Math.floor((Math.random()*5) + 5);
var discount = "<p>Your Discount is "+my_num+"%</p>";
$( ).append(discount);
$(".guess_box").each( function(){
$(this).unbind('click');
});
});
index.html
my_scripts.js
Разложите магниты в соответствии со структурой файлов проекта.
Убедитесь в том, что вы знаете, как правильно организовать разде-
ление кода HTML, CSS и jQuery. В будущем вы должны безошибочно
справляться с этой задачей.
Развлечения с магнитами
132 глава 3
решение упражнения
<!DOCTYPE html>
<html>
<title>Jump for Joy</title>
<link href="styles/styles.css" rel="stylesheet">
</head>
<div id="header">
<h2>Jump for Joy Sale</h2>
<div id="main">
<div ><img src="images/jump1.jpg"/></div>
<div class="guess_box"><img src="images/jump2.jpg"/></div>
<div class="guess_box"><img src="images/jump3.jpg"/></div>
<div ><img src="images/jump4.jpg"/></div>
</div>
<script src="scripts/ "></script>
< src="scripts/my_scripts.js"></script>
</body>
<html>
$(document).ready(function() {
$( ).click( function() {
var = Math.floor((Math.random()*5) + 5);
var discount = "<p>Your Discount is "+my_num+"%</p>";
$( ).append(discount);
$(".guess_box").each( function(){
$(this).unbind('click');
});
});
index.html
my_scripts.js
"
pts/my scripts.js"></scrip
jquery-1.6.2.min.js
cument).ready(func
)
var = Ma
".guess_box"
ain >
v >
v class="guess_box"><im
class="guess_box"
v class guess_box ><im
v >
>
class="guess_box"
p
< sr
body>script
});
});
});
p
<div id="maid= ma</div>
) this
/
<div id="h
<body>
discount =
=
g _
my_num
tml>
<title>Jump
<head>
Разложите магниты в соответствии со структурой файлов проекта.
Убедитесь в том, что вы знаете, как правильно организовать разде-
ление кода HTML, CSS и jQuery. В будущем вы должны безошибочно
справляться с этой задачей.
Развлечения с магнитами – решение
дальше � 133
события и функции jquery
А как было бы замечательно, если бы единожды написанный код jQuery можно
было использовать снова и снова?Но это, конечно, всего лишь мечты...
134 глава 3
повторное использование кода
$(document).ready(function(){
$("#clickMe").click(function(){
//...
});
$(".guess_box").click(function(){
//...
});
});
Èñïîëüçîâàíèå ôóíêöèé
От добавления и удаления событий на страницах мы переходим к другой полезной возможности, которая повысит эффективность использования jQuery на наших сайтах: функциям.
Функцией называется программный блок, отделенный от основ-ного кода, который можно в любой момент выполнить в сценарии.
Представьте себе, мы постоянно использовали функции в этой книге. Помните эти конструкции?
В jQuery существует много готовых функций, но вы так-же можете писать собственные функции для реализации возможностей, не поддерживаемых в jQuery. Единожды написанную функцию можно использовать снова и снова без повторения ее кода в сценарии. Чтобы выполнить код функции, достаточно вызвать ее по имени.
Смотрите: функции!
Вспомните: эти блоки уже использовались в нашем коде!
В сущности, пользовательская
функция — это фрагмент кода
jQuery, которому присвоено имя
для удобства использования.
дальше � 135
события и функции jquery
Êàê óñòðîåíà ôóíêöèÿ
Определение функции связывает имя с выполняемым кодом. Синтаксис большинства базовых функций JavaScript выгля-дит так:
Имена функций? Но ведь у функций, которые мы ис-
пользовали прежде, имен не было. Почему же теперь мы стали присваивать имена?
Хороший вопрос.Присваивание имени позволяет вызывать функцию в разных ме-стах программного кода. Возмож-ности использования безымян-ных функций (также называемых анонимными функциями) весьма ограничены. Давайте познако-мимся с анонимными функциями поближе, чтобы вы увидели, какие неудобства возникают при отсут-ствии имени.
function name ()
}
{
run this code
Все начинает-ся с ключевого слова function.
Имя функции
По круглым скобкам
можно сразу опреде-
лить, что перед нами
функция.
Открываю-щая фигур-ная скобка
Функция заверша-ется закрывающей фигурной скобкой.
В теле функции размещается вы-полняемый код.
function myFunc1(){
$("div").hide();
}
var myFunc2 = function() {
$("div").show();
}
Èìåíà ôóíêöèé
Îáúÿâëåíèå ôóíêöèè
Ôóíêöèîíàëüíîå âûðàæåíèå
Имя функции
Функция присваивается специальной переменной.
Присвоить имя функции можно двумя способами.
В именованном функциональном выражении функ-ция определяется как часть внешней конструкции (чаще всего команды присваивания):
Первый способ — объявление функции — опреде-ляет именованную функциональную перемен-ную без присваивания. Объявления начинаются с ключевого слова function:
136 глава 3
что в имени тебе моем?
В: Чем объявление функции отличается от именован-ного функционального выражения?
О: Прежде всего временем использования. Хотя обе фор-мы делают одно и то же, функция, определяемая в форме именованного функционального выражения, может использоваться в коде только после выполнения команды, содержащей выражение. С другой стороны, функция, опре-деляемая в форме объявления функции, может вызы-ваться в любом месте страницы (даже в обработчике onload).
В: Существуют ли ограничения для имен, присваи-ваемых функциям?
О: Да. Имена функций не могут начинаться с цифр, в них не допускается использование математических операторов и знаков препинания, хотя допускается символ подчерки-вания (_). Кроме того, имя функции не может содержать пробелы, и в именах функций и переменных учитывается регистр символов.
Àíîíèìíàÿ ôóíêöèÿ
Анонимные функции определяются без имени и выполняются непосредственно при определении в коде. Все переменные, объ-явленные в таких функциях, доступны только во время выполнения функции.
Функцию, которой не присвоено имя,нельзя вызывать в других местах.
$(document).ready(function() {
$(".guess_box").click( function() {
var my_num = Math.floor((Math.random()*5) + 5);
var discount = "<p>Your Discount is "+my_num+"%</p>";
$(this).append(discount);
$(".guess_box").each( function(){
$(this).unbind('click');
});
});
});
my_scripts.js
Эта функция не будет вызы-ваться в других местах кода.
переменные
Если вы захотите использовать этот код в другом месте, его придется про-дублировать.
Будьте осторожны!
частоЗадаваемые
вопросы
дальше � 137
события и функции jquery
Ранее мы видели, как анонимные функции используются в качестве обработчиков событий. Пользовательские именованные функции тоже могут использоваться для обработки собы-тий, для чего они вызываются непосредственно из кода. Вернемся к примерам именованных функций, приведенным двумя страницами ранее.
Разложите магниты так, чтобы код, проверяющий скидку, был выделен
в именованную функцию checkForCode, которая используется в каче-
стве обработчика события click для областей div.
click
append
discount
"+my_num+"
checkForCode
function
{
)
()
var
}
(
myFunc1();
$("#myElement").click(myFunc2);
Это означает, что после щелчка на myElement области div будут видны.
Области div скрыва-ются в соответствии с объявлением функции.
Функция вызывается
в программном коде.Здесь нужны круглые скобки.
Когда функция вызывается как обработчик со-бытия, круглые скобки не нужны.
Имена функций
Функция вызыва-
ется как обра-
ботчик события.
function myFunc1(){
$("div").hide();
}
var myFunc2 = function() {
$("div").show();
}
Îáúÿâëåíèå ôóíêöèè
Ôóíêöèîíàëüíîå âûðàæåíèå
$(document).ready(function() {
$(".guess_box").click( checkForCode );
var my_num = Math.floor((Math.random()*5) + 5);
discount = "<p>Your Discount is "+my_num+"%</p>";
$(this).append( );
$(".guess_box").each( function(){
$(this).unbind(' ');
});
});
my_scripts.js
Èìåíîâàííûå ôóíêöèè êàê îáðàáîò÷èêè ñîáûòèé
Развлечения с магнитами
138 глава 3
решение упражнения
)
Объявление функции
Разложите магниты так, чтобы код, проверяющий скидку, был выделен
в именованную функцию checkForCode, которая используется в каче-
стве обработчика события click для областей div.
Лишние магниты
Отличная работа! Внесите эти изменения в файл с кодом. Поздравляем, вы создали свою первую функцию и исполь-зовали ее как функцию-обработчик события click.
$(document).ready(function() {
$(".guess_box").click( checkForCode );
var my_num = Math.floor((Math.random()*5) + 5);
discount = "<p>Your Discount is "+my_num+"%</p>";
$(this).append( );
$(".guess_box").each( function(){
$(this).unbind(' ');
});
});
my_scripts.js
()
);
}
ndom()d
{
y_
d
$(this)
var
ch( functio
click
p
)discount
) (
Math floor((Mathth
checkForCode
( g _
var my num = M
)
= M
function
append
)
ap"+my_num+"
d
(
Наша именованная
функция как обработчик
Команда завершается символом «;».
Генератор случай-
ных чисел (использо-
вался в главе 2)
Вывод сообщения
о скидке на экран
Удаление события click из всех областей, как было показано ранее в этой главе.
Задание !
Как бы вы написали функцию, скрывающую сообщение о скидке в случайной области div, и другую функцию, генерирующую случайное число для самого сообщения о скидке? Подсказка: генератор случайных
чисел может использоваться
как в существующей функции
checkForCode, так и в функции
вывода сообщения о скидке в слу-
чайной области div.
Развлечения с магнитами. Решение
Мозговой
штурм
дальше � 139
события и функции jquery
Иногда бывает нужно, чтобы результат работы функции изменялся в зависимости от дополнитель-ной информации, передаваемой при вызове.Наши функции могут получать переменные — как говорилось в главе 2, переменные используются для хранения информа-ции, которая может изменяться со временем. Давайте вспом-ним, как работают переменные.
Получается, что функция должна работатьпо-разному в зависимости от того, на какой об-
ласти div щелкнул пользователь...Как бы это сделать?
var pts = 250;
Ключевое слово var
объявляет переменную.
За ключевым словом var указывается имя переменной. Так значение переменной за-
дается в программном коде.
При объявлении пере-менной интерпретатор JavaScript выделяет блок памяти браузера, в ко-тором будут храниться ваши данные.
pts
Переменной присваивается имя, по которому вы бу-дете позднее обращаться к ней в своем сценарии.
pts
=250Значение, сохраняемое в переменной, указывается после знака равенства.
А ведь мы уже использовали пере-менные в своем коде, помните? var my_num = Math.floor((Math.random()*5) + 5);
var discount = "Your Discount is "+my_num+"%";
140 глава 3
пожалуйста, передайте переменную
Ïåðåäà÷à ïåðåìåííûõ ôóíêöèÿì
Переменные, передаваемые функциям, называются аргументами. (Иногда также их называют параметрами.) Давайте разберемся, как же происходит передача аргументов функциям.
Нашей функции не нужно знать, какие данные хранятся в переменной; она просто выводит ее текущее содержимое. Таким образом, для измене-ния результата работы функции достаточно изменить передаваемую пере-менную (вместо изменения кода самой функции, что безусловно усложнит ее повторное использование!).
function welcome (name) {
alert ("Hello"+ name);
}
// Вызов нашей функции
welcome("John");
Имя функции
Аргумент используется в вычислениях.
Имя аргумента
function name (
}
{
выполняемый код
)аргументы
Аргументы перечисля-
ются в круглых скобках.
Объединение переменных и функций на первый взгляд выглядит невразумительно.
Однако вы можете рассматривать свою функцию как рецепт — допустим, рецепт коктейля. Набор
простых, легко повторяемых действий для создания коктейля (порцию того, немного этого, перемешать и т. д.) является аналогом функции, а ингредиен-ты — аналогами передаваемых переменных. Кто-нибудь желает джин-тоник?
Р А СС Л А Б Ь Т Е С Ь
дальше � 141
события и функции jquery
Ôóíêöèÿ òàêæå ìîæåò âîçâðàùàòü çíà÷åíèÿ
Функция возвращает результат своей работы при помощи команды, состоящей из ключевого слова return и возвра-щаемого значения. Результат передается в точку вызова функции для дальнейшего использования. Возвращаемое значение
может быть числом, строкой
текста и даже элементом
DOM (объектом).function multiply (num1, num2) {
var result = num1*num2;
return result;
}
// Call our function
var total = multiply (6, 7);
alert (total);
Имя функции
Операции с аргу-
ментами
Имена аргументов
Возвращаемое значение
Итак, теперь вы умеете создавать собственные функции. Включите
в файл my_scripts.js новую функцию, которая получает один аргумент
(с именем num) и возвращает случайное число в интервале от 0 до пе-
реданного числа. Присвойте функции имя getRandom.
my_scripts.jsПодсказка: Вспомните код, который мы использовали для гене- рирования случайных чисел. Подумайте, как оформить его в виде функции.
Возьми в руку карандаш
142 глава 3
решение упражнения
function getRandom(num){
var my_num = Math.floor(Math.random()*num);
return my_num;
}
my_scripts.js
ДжимФрэнк Джо
Джим: Кроме новой функции getRandom, нам понадобится еще одна функция.
Фрэнк: Точно — для включения кода скидки в случайное выбран-ное изображение... Кстати, в ней можно использовать функцию getRandom.
Джо: Логично. После щелчка мы проверяем, правильно ли поль-зователь выбрал изображение.
Джим: Погодите-ка, что? Как проверить, правильно ли выбрано изображение?
Фрэнк: Условная конструкция!
Джим: Что?
Фрэнк: Условные конструкции позволяют проверить некоторое условие и выполнить код в зависимости от результата проверки.
Джо: Например, можно проверить, что переменная имеет опре-деленное значение или что два значения равны?
Фрэнк: Точно! Мы даже можем проверить, находится ли элемент внутри другого элемента... Думаю, здесь нам это пригодится.
Имя функции Имя аргумента
Функция возвращает случайное число.
Итак, теперь вы умеете создавать собственные функции. Включите
в файл my_scripts.js новую функцию, которая получает один аргумент
(с именем num) и возвращает случайное число в интервале от 0 до пе-
реданного числа. Присвойте функции имя getRandom.
Функции и аргументы — это, конечно, хорошо, но насколько мы приблизились к завершению кода страницы «Прыгаем
от радости»?Выглядит неплохо! Но это
только начало — посмо-
трим, что ваша группа
скажет о выборе «правиль-
ного» изображения…
Возьми в руку карандаш Решение
дальше � 143
события и функции jquery
Óñëîâíûå êîíñòðóêöèè è ïðèíÿòèå ðåøåíèé
В jQuery используются условные конструкции JavaScript, позволяю-щие выполнять разный код в зависимости от решения, принято-го в коде на основе уже имеющейся информации. Ниже приведен пример использования условных конструкций JavaScript. Другие примеры будут представлены в главе 6.
if( myBool == true ){
// Здесь что-то делаем!
}else{
// Иначе делаем что-то другое!
}
Проверяемое условие
Оператор проверки
равенства
Начало условной команды if
Переменная JavaScript
Код, который должен выполняться, если условие истинно.
Код, который должен выпол-няться, если усло-
вие ложно.
Примечание: команда if может и не содержать секции else, но вреда от нее не будет.
Расставьте магниты так, чтобы создать именованную функцию hideCode, которая при
помощи условной конструкции прячет новый элемент span с идентификатором has_discount в случайно выбранном элементе div класса .guess_box.
span
".guess_box"
has_discount
getRandom
hideCode
});
var = function (){
var numRand = (4);
$( ).each(function(index, value) {
if(numRand == index){
$(this).append("<span id=' '></ >");
return false;
}
}
{
)
()
}(
my_scripts.js
Развлечения с магнитами
144 глава 3
решение упражнения
var = function (){
var numRand = (4);
$( ).each(function(index, value) {
if(numRand == index){
$(this).append("<span id=' '></ >");
return false;
}
}
my_scripts.js
Расставьте магниты так, чтобы создать именованную функцию hideCode, которая при помощи
условной конструкции прячет новый элемент span с идентификатором has_discount в слу-
чайно выбранном элементе div класса .guess_box. Далее приводится наше решение.
Индекс элемента списка обозначает его текущую позицию в списке.
Индексы элементов всегда начинаются с 0.
Таким образом, индекс первого элемента равен 0, индекс второго — 1, и т. д. Мы еще вернемся к теме индексирования при рассмотрении массивов и цик-лов в главе 6.
>"span
)
if( R d i d
".guess_box"
'>has_discount
(getRandom
var numRand
hideCode
}
});
Условная кон-струкция срав-нивает текущую позицию списка со случайным
числом.
Наша именованная функция
Вызов функции, генериру-
ющей случайное число
Выход из цикла .each() Элемент discount до-
бавляется в элемент
класса .guess_box.
Развлечения с магнитами. Решение
Будьте осторожны!
дальше � 145
события и функции jquery
Потрясающе! Скидка каждый раз прячется в новом изображении. Да эти
функции действительно полезны!
function checkForCode(){
var discount;
if($.contains(this, document.getElementById("has_discount") ) )
{
var my_num = getRandom(5);
discount = "<p>Your Discount is "+my_num+"%</p>";
}else{
discount = "<p>Sorry, no discount this time!</p>" ;
}
$(this).append(discount);
$(".guess_box").each( function(){
$(this).unbind('click');
});
}
my_scripts.js
Фрэнк: Да, безусловно. Нам удалось спрятать скидку, но как те-перь мы ее найдем?
Джим: Эээ... хороший вопрос. Я не знаю.
Джо: Полагаю, мы снова воспользуемся волшебными условными конструкциями?
Фрэнк: Точно. Вместо того чтобы выбирать случайный индекс в списке элементов .guess_box, мы переберем элементы и по-следовательно проверим, содержат ли они спрятанный элемент has_discount.
Джо: «Содержат?» Фрэнк, а ведь в этом что-то есть.
Фрэнк: Угу. Давайте посмотрим, чем нам поможет jQuery.
Задание!
Включите в функцию checkForCode но-вый код, основанный на идеях Джима, Фрэнка и Джо.Условная кон-
струкция про-веряет, нашел ли пользователь элемент div со скидкой.
Объявление переменной
discount
Этот метод jQuery проверя-ет, содержит ли первый пара-метр то, что определяется вторым пара-метром.
Текущий элемент —т. е. элемент,вызвавший функцию.
Поиск элемента DOM с идентификатором has_discount.
В зависимости от того, нашел пользователь скидку или нет, выводятся разные сообщения.
146 глава 3
пользовательские функции
Пришло время написать несколько функций: первая гене-рирует случайное число, вторая прячет признак скидки, а третья проверяет наличие спрятанного признака.
$(document).ready(function() {
$(".guess_box").click( checkForCode );
function getRandom(num){
var my_num = Math.floor(Math.random()*num);
return my_num;
}
var hideCode = function(){
var numRand = getRandom(4);
$(".guess_box").each(function(index, value) {
if(numRand == index){
$(this).append("<span id='has_discount'></span>");
return false;
}
});
}
hideCode();
function checkForCode(){
var discount;
if($.contains(this, document.getElementById("has_discount") ) )
{
var my_num = getRandom(5);
discount = "<p>Your Discount is "+my_num+"%</p>" ;
}else{
discount = "<p>Sorry, no discount this time!</p>" ;
}
$(this).append(discount);
$(".guess_box").each( function(){
$(this).unbind('click');
});
}
}); //End document.ready()
my_scripts.js
Функция вызывается при щелчке на элементе, принад-лежащем классу .guess_box.
Именованная функция, скрывающая признак скидки
А эта функция проверя-
ет и сообщает размер
скидки.
Вызов именованной функции
Функция, генерирую-
щая случайное число
Задание!
дальше � 147
события и функции jquery
Íî ýòî åùå íå âñå
Только вы решили, что работа над рекламной акцией «Прыгаем от радости» завершена, как у Эмили появились новые требования…
От: ЭмилиТема: RE: Рекламная акция «Прыгаем от радости»
Привет,
Спасибо за все, что ты для нас сделал.
Я подумала, а нельзя ли «подсветить» изображение перед щелчком?
Пользователь будет точно знать, на каком изображении он щелкает, а это
поможет избежать недоразумений.
Кроме того, нельзя ли вывести сообщение о скидке в удобной текстовой
области под изображениями на экране? Допустим, код скидки будет состо-
ять из текста и числа? Я подумала, что это будет удобно... Да, и нельзя ли,
чтобы число было больше 10? Скажем, в диапазоне от 1 до 100?
Напиши, сможешь ли ты внести эти небольшие изменения.
--Эмили Сондерсjumpforjoyphotos.hg
Требования:
Вы уже знаете, что делать. Выделите требования из сообщения Эмили.
Возьми в руку карандаш
148 глава 3
решение упражнения
Требования:
Вы уже знаете, что делать. Выделите требования из сообщения Эмили.
• Визуально выделить область перед щелчком, чтобы пользо-ватель точно знал, какой вариант он выбирает.
• Вывести код скидки в специальной области страницы. Код должен состоять из текста и числа от 1 до 100.
Как показать пользователю, на какой области он собирается щелкнуть, до выполнения щелчка?
В: Обязательно ли указывать возвра-щаемое значение во всех функциях?
О: Формально необязательно. Все функции возвращают значение независимо от того, ука-зали вы его или нет. Если возвращаемое зна-чение не указано, то функция возвращает не-определенное значение undefined. Если ваш код не может обработать undefined, это приведет к ошибке. Следовательно, воз-вращаемое значение все же лучше указывать, даже в простейшем виде return false;.
В: Существуют ли ограничения для аргументов или параметров, передава-емых функции?
О: Нет, функции можно передать любой объект, элемент, переменную или значение. Также можно передать большее количество параметров, чем ожидает ваша функция. Лишние параметры игнорируются. Если передать слишком мало параметров, то недостающим параметрам автоматически присваивается undefined.
В: Что делает метод $.contains?
О: Это статический метод библиотеки jQuery, который получает два параметра. Он проверяет все дочерние элементы пер-вого параметра, ищет среди них второй па-раметр и возвращает true или false в зависимости от результата. В нашем примере выражение $.contains(document.body, document.getElementById"header")) истинно; с другой стороны, выражение $.contains(document.getElementById("header"), document.body) будет ложно.
В: Что такое «статический метод» jQuery?
О: Это означает, что функция связана с библиотекой jQuery, а не с конкретным объектом. Для вызова таких методов не нужен селектор, достаточно указать имя jQuery или его сокращенную форму ($).
В: Что делают index и value в нашей функции-обработчике . each?
О: index обозначает текущую итерацию цикла (начиная с 0 для первого элемен-та массива, возвращаемого селектором). value обозначает текущий объект, это аналог $(this) в цикле .each.
В: Почему наш цикл .each в функции hideCode возвращает false?
О: Команда return false в цикле .each приказывает прервать цикл и продолжить выполнение кода. При возвращении любого значения, отличного от false, цикл пере-ходит к следующему элементу в списке. В нашем примере скидка уже спрятана, поэтому остальные элементы перебирать необязательно.
Мозговой
штурм
частоЗадаваемые
вопросы
Возьми в руку карандаш Решение
дальше � 149
события и функции jquery
<html>
<head>
<link href="styles/test_style.css" rel="stylesheet">
</head>
<body>
<div id="header" class="no_hover"><h1>Header</h1></div>
<button type="button" id="btn1">Click to Add</button>
<button type="button" id="btn2">Click to Remove</button>
<script src="scripts/jquery.1.6.2.js"></script>
<script src="scripts/my_test_scripts.js"></script>
</body>
</html>
class_test.html
Ìåòîäû ìîãóò èçìåíÿòü CSS
Следующая задача — «подсветить» область, на которую наведен указа-тель мыши, перед щелчком. Для изменения внешнего вида элемента проще всего воспользоваться CSS и классами CSS.
К счастью, jQuery позволяет легко назначать элементам классы CSS и удалять их при помощи простых, удобных методов. Давайте посмо-трим, как применить их в нашем решении.
Создайте новые файлы отдельно от существующих и проследите за тем, как работают новые методы. Это поможет вам понять, как происходит «под-светка» области перед щелчком.
$(document).ready(function() {
$("#btn1").click( function(){
$("#header").addClass("hover");
$("#header").removeClass("no_hover");
});
$("#btn2").click( function(){
$("#header").removeClass("hover");
$("#header").addClass("no_hover");
});
});
.hover{
border: solid #f00 3px;
}
.no_hover{
border: solid #000 3px;
}
my_test_scripts.js
test_style.css
Помните по главам 1 и 2?
Готово к употреблению
150 глава 3
тест-драйв
Äî ùåë÷êà
Ïîñëå ùåë÷êà
Здорово! Если бы все было так просто... А изменение CSS может срабатывать по другим причинам, кроме события click?
Да, может. И ничуть не сложнее...Переключение CSS может происходить по событию любого типа, но для нашего решения нужен вполне определенный тип события. Вернитесь к списку на с. 116 и попробуйте определить, какое событие следует использовать в нашем примере.
Ä ê
Ï
Откройте только что созданный файл class_test.html в браузере. При щелчке на кнопке Add класс применяется к области div с идентификатором header. Кнопка Remove снова удаляет назначенный класс!
Тест-драйв
дальше � 151
события и функции jquery
Äîáàâëåíèå ñîáûòèÿ hover
В параметрах события hover могут передаваться две функции-обработчика для событий mouseenter и mouseleave. Эти функции могут быть как именованными, так и анонимными. Внимательно просмотрите код тестового сценария и подумай-те, как использовать событие hover для изменения внешнего вида элемента при наведении на него указателя мыши.
$(".guess_box").hover(
function () {
// Обработчик события mouseenter
.
},
function () {
// Обработчик события mouseleave
});
Метод jQuery addClass назна-
чает элементу класс CSS. Он
не влияет на другие классы CSS,
уже назначенные элементу.
Метод jQuery removeClass отменяет класс CSS, на-значенный элементу.
Измените файлы my_style.css и my_scripts.js так, чтобы изображения визуально выде-лялись при наведении на них указателя мыши. Вам понадобится новый класс CSS и две функции-обработчика (после функции checkForCode), использующие ме-тоды addClass и removeClass для назначения/отмены класса CSS. Мы уже на-писали заготовки этих функций; вам остается лишь заполнить пропуски.
my_scripts.js
my_style.cssmy_style.css
Упражнение
Метод jQuery addClass назна-
чает элементу класс CSS. Он
не влияет на другие классы CSS,
уже назначенные элементу.
Метод jQuery removeClass отменяет класс CSS, на-значенный элементу.
$(document).ready(function() {
$("#btn1").click( function(){
$("#header").addClass("hover");
$("#header").removeClass("no_hover");
});
$("#btn2").click( function(){
$("#header").removeClass("hover");
$("#header").addClass("no_hover");
});
});
my_test_scripts.js
152 глава 3
Тест-драйв
решение упражнения
3
Откройте в браузере файл index.html, который включает ваш новый файл my_scripts.js. Наведите мышь на изображение и посмотрите, изменится ли внешний вид рамки.
Хмм... Рамка Хмм... Рамка изображения изображения меняет цвет, меняет цвет, но работа еще но работа еще не закончена...не закончена...
Это новый класс.
$(".guess_box").hover(
function () {
// this is the mouseenter event handler
$(this).addClass("my_hover");
},
function () {
// this is the mouseleave event handler
$(this).removeClass("my_hover");
});
.my_hover{
border: solid #00f 3px;
}
my_scripts.js
my_style.cssmy_style.cssНазначает класс CSS элементу, на который пользователь наводит ука-затель мыши, при помощи анонимной функции-об-работчика для события mouseenter.
Метод jQuery addClass назначает эле-менту класс CSS. Он не влияет на другие
классы, назначенные элементу ранее.
Метод jQuery removeClass отменяет назначение класса CSS элементу.
Анонимная функция-обработчик
для события mouseleave.
У нас есть класс CSS, для управления которым используется событие hover.
дальше � 153
события и функции jquery
Безусловно, мы продвигаемся вперед, но сообщение все еще выводится в неправильном месте и выглядит не так, как нас просили. Вдобавок в первом сообщении осталось еще одно требова-ние, которое мы не выполнили. Вот как список требований выглядит на данный момент.
• После того как посетитель выбрал изображение и щел-кнул на нем, следует сообщить, была ли его догадка успешной. Если изображение было выбрано правильно, нуж-но вывести величину скидки.
Это требование еще из первого сообщения!
Измените код checkForCode так, чтобы функция:
1) выводила код скидки в специальной области страницы;
2) создавала код в виде комбинации из букв и числа в интер-вале от 1 до 100;
3) показывала посетителю, где был спрятан код, если попытка оказалась неудачной.
Чтобы упростить вашу задачу, мы создали классы CSS. Включите их в файл my_styles.css для обозначения того, правильно ли было вы-брано изображение.Заодно разместите под четырьмя изображения-ми элемент span с идентификатором result, в котором будет выводиться код скидки.
.discount{
border: solid #0f0 3px;
}
.no_discount{
border: solid #f00 3px;
}
my_style.cssmy_style.css
Åùå íåìíîãî...
• Визуально выделить область перед щелчком, чтобы пользователь точно знал, какой вариант он выбирает.
• Вывести код скидки в специальной области страницы. Код должен состоять из текста и числа от 1 до 100.
Упражнение
154 глава 3
решение упражнения
Функция checkForCode дополнена всеми необходимыми составляющими: отдельным местом на экране для вывода кода скидки; самим кодом скидки, состоящим из текста и чис-ла от 1 до 100; и выводом информации о местонахождении скидки после щелчка.
function checkForCode(){
var discount;
if($.contains(this, document.getElementById("has_discount") ) )
{
var my_num = getRandom(100);
discount = "<p>Your Code: CODE"+my_num+"</p> ;
}else{
discount = "<p>Sorry, no discount this time!</p>" ;
}
$(".guess_box").each(function() {
if($.contains(this, document.getElementById("has_discount")))
{
$(this).addClass("discount");
}else{
$(this).addClass("no_discount");
}
$(this).unbind();
});
$("#result").append(discount);
} // End checkForCode function
my_scripts.js
Проверяем, со-держит ли те-кущая область код скидки, с использова-нием функции jQuery contains.
...а если не уга-дал — исполь-зуем другое оформление.
Если поль-зователь угадал -визуально изменяем область, чтобы обо-значить ме-стонахожде-ние скидки...
Сообщение выводится на стра-
нице в специальной области.
Используем функцию getRandom для расширения числовой состав-ляющей кода до 100.
Выбираем выводимое сообщение в зависи-мости от того, нашел пользова-тель скидку или нет.
дальше � 155
события и функции jquery
Итак, функция checkForCode была успешно изменена. Проверьте, как рабо-тают новые возможности сайта. (Файл с окончательной версией кода можно загрузить по адресу http://thinkjquery.com/chapter03/end/scripts/my_scripts.js.)
Çàãðóæåííàÿ ñòðàíèöà
Ñêèäêè íåò
Êîä ñêèäêè
Отличная работа! Совсем другое дело. Рекламная акция повысит популярность
сайта, а Эмили сможет заработать!
Тест-драйв
156 глава 3
инструментарий jQuery
Âàø èíñòðóìåíòàðèé jQuery
Глава 3 осталась позади, а ваш творческий инструментарий расширился: в нем появи-лись события, пользовательские функции и условные конструкции.
Функции
Фрагменты кода, которые мо-
гут использоваться в других
местах…
…но только в том случае,
если
им присвоены имена.
Безымянные функции выпол-
няются только в точке свое
го
определения и не могут исполь-
зоваться в других местах.
Функции могут получать пере-
менные (называемые аргумента-
ми или параметрами), а также
могут возвращать результаты
своей работы.
Условные конструкцииПроверка логических условий (if XYZ = true) перед выпол-нением каких-либо операций.Часто содержат секцию else
для случая, если проверяемое условие ложно, но присут-ствие этой секции необяза-тельно.
События
Объекты, которые упроща-
ют взаимодействие пользо-
вателя с веб-страницей.
Всего существует около
30 типов событий. Практи-
чески все, что происходит
в браузере, может стать
источником события.
ГЛА
ВА 3
Операции со структурой страниц в jQuery4
Изменение DOM
Завершение загрузки страницы еще не означает, что ее структура останется неизменной. В главе 1 было показано, как в процессе загрузки страницы строится модель DOM, определяющая ее структуру. В этой главе вы научитесь перемещаться по дереву DOM, работать с иерархией эле-ментов и отношениями «родитель/потомок» для изменения структуры страницы «на ходу» средствами jQuery.
Родители у насобщие, но мы-товсе равно разные!
158 глава 4
одна страница свяжет их воедино
У Александры, шеф-повара небольшого кафе в городке Интернет-виль, есть для вас работа. Ей приходится вести разные веб-страницы для двух разных версий своего меню: обычной и вегетарианской. Александра хочет создать одну страницу, которая бы при необходи-мости могла изменить меню для клиентов-вегетарианцев.
Мы разместили меню в Сети несколько лет назад, и клиентам это понравилось! Я хочу
добавить к нему кнопки, позволяющие клиентам изменять веб-меню «на ходу».
Èíòåðàêòèâíîå ìåíþ
дальше � 159
операции со структурой страниц в jQuery
Âåãåòàðèàíöû, âïåðåä!
Прежде чем браться за код jQuery, давайте посмотрим, какие файлы HTML и CSS нам прислал веб-дизайнер и насколько хороши их стиль и структура.
Нам нужна кнопка вегетарианского меню, которая
автоматически подставляет вегетарианские аналоги
в веб-меню.
Замена осуществляется по следующим правилам:
— у рыбных блюд аналогов нет, они просто удаля-
ются из меню;
— гамбургеры заменяются гигантскими шампиньо-
нами;
— мясные ингредиенты (кроме гамбургеров) и яйца
заменяются тофу.
Нам также понадобится вторая кнопка, восстанавли-
вающая меню в исходном состоянии.
P. S. И еще хотелось бы, чтобы замененные вегета-
рианские блюда в меню были помечены — например
зеленым листом.
Веб-дизайнер пришлет файлы текущего меню,
чтобы ты мог приступить к работе.
Вот чего хочет Александра:
ГГГррраааннн--ккаа
фее ИИИннтттеернннееетттвввииилляя
На этот раз отдельного упражнения с записью требо-ваний не будет (хотя, наверное, вы уже к ним привыкли?). Тем не менее обязательно изложите суть требований своими слова-ми — это поможет вам четко представлять, что именно мы здесь строим.
160 глава 4
построение дерева DOM
body
h4
li
li
li
ul class="menu_list"
li
li
li li
li
li
li
li
li
lili
li
ul class="menu_list"
ul class="menu_list"
ul class="menu_entrees"
div class="left_col"
div class="menu_wrapper"
Проанализируйте текущую структуру веб-меню и постройте диаграмму его
модели DOM. Ниже вы найдете все магниты с элементами, необходимыми для
заполнения всех пропусков. Достройте дерево, используя фрагмент разметки
HTML на следующей странице. Позиции для размещения магнитов обозначены
кружочками. Мы уже разместили несколько элементов за вас.
Развлечения с магнитами
дальше � 161
операции со структурой страниц в jQuery
Фрагмент реальной страницы HTML
<body> <div id="menu_wrapper"> <div class="left_col"> <h4>Dinner Entrees</h4> <ul class="menu_entrees"> <li>Thai-style Halibut <ul class="menu_list"> <li>coconut milk</li> <li>pan-fried halibut</li> <li>early autumn vegetables</li> <li>Thai spices </li> </ul> </li> <li>House Grilled Panini <ul class="menu_list"> <li>prosciutto</li> <li>provolone</li> <li>avocado</li> <li>sourdough roll</li> </ul> </li> <li>Southwest Slider <ul class="menu_list"> <li>whole chiles</li> <li>hamburger</li> <li>pepperjack cheese</li> <li>multigrain roll</li> </ul> </li> </ul> </div> </div></body>
index.html
162 глава 4
решение упражнения
Похоже, все ингредиенты создаются как дочерние элементы по
отношению к родительским элементам списка блюд. Такую раз-
метку никак не назовешь предельно понятной или однозначной,
не правда ли?
Развлечения с магнитами. Решение
body
h4
li li li
ul class="menu_list"
lili li li li lili li li lili li
Каждое блюдо представляет
собой пункт списка…
К счастью, текущая версия веб-меню обладает четкой структурой.
…с перечнем ингредиентов
(ul.menu_list) в виде вло-
женного неупорядоченного
списка.
Каждый ингредиент каждого блюда пред-ставлен пунктом списка.
Меню использует неупорядоченный
список для хранения блюд.
ul class="menu_list"
ul class="menu_list"
ul class="menu_entrees"
div class="left_col"
div class="menu_wrapper"
Нужно написать селекторы для поиска ингреди-ентов, которые нужно изменить. На этом уровне любой ингредиент является пунктом списка……как же отличить заменя-емые ингредиенты от всех остальных?
дальше � 163
операции со структурой страниц в jQuery
Фрагмент реальной страницы HTML
<body> <div id="menu_wrapper"> <div class="left_col"> <h4>Dinner Entrees</h4> <ul class="menu_entrees"> <li>Thai-style Halibut <ul class="menu_list"> <li>coconut milk</li> <li>pan-fried halibut</li> <li>early autumn vegetables</li> <li>Thai spices </li> </ul> </li> <li>House Grilled Panini <ul class="menu_list"> <li>prosciutto</li> <li>provolone</li> <li>avocado</li> <li>sourdough roll</li> </ul> </li> <li>Southwest Slider <ul class="menu_list"> <li>whole chiles</li> <li>hamburger</li> <li>pepperjack cheese</li> <li>multigrain roll</li> </ul> </li> </ul> </div> </div></body>
index.html
Четкая структура веб-страницы (HTML) существенно упрощает написание кода jQuery. Однако элементы ингредиентов, которые нужно найти, не имеют пометок, которые бы упрощали программирование jQuery. Как же упростить выбор элементов?
Мозговой
штурм
164 глава 4
классные ингредиенты
Íàçíà÷åíèå êëàññîâ ýëåìåíòàì
Как было показано во всех предыдущих главах, эффективность поиска элементов веб-страниц средствами jQuery можно повысить за счет правильного определения структуры HTML и CSS. Чтобы структура по-настоящему заработала, следует включить в таблицу стилей классы и иден-тификаторы и задать соответствующие классы и идентификаторы в атрибутах элементов HTML. Это упростит выбор элементов и сэкономит ваше время при программировании.
В jQuery роль селекторов не ограничивается управлением внешним видом и поведением стра-ницы. Селекторы также используются в jQuery для идентификации элементов страниц.
.meat
<li class="meat">turkey</li>
<li class="meat">chicken</li>
<li class="meat">eggs</li>
<li class="meat">lamb shoulder</li>
Можно написать отдельный се-лектор для каждого ингредиента, который нужно найти на странице...
…а можно сгруппиро-вать их в классе и на-писать один селектор для идентификации сразу всех элементов.
<li>turkey</li><li>chicken</li> <li>eggs</li> <li>lamb shoulder</li>
При задании атрибута class каждого элемен-та, входящего в список, этот элемент вклю-чается в класс meat («мясо»).
Что я делаю в категории
«мясо»?
Да ладно, это же не магазин... Просто нам нужно короткое, удоб-ное имя класса.
дальше � 165
операции со структурой страниц в jQuery
Найдите ингредиенты, которые должны заменяться вегетарианскими аналогами, и назначьте каждому из них соответствующий класс (fish, meat или hamburger). Если ингредиенту не ну-жен класс, оставьте строку пустой. Структура кода HTML соответствует внешнему виду меню на странице.
<li>Thai-style Halibut
<ul class="menu_list">
<li >coconut milk</li>
<li >pan-fried halibut</li>
<li >lemongrass broth</li>
<li >vegetables</li>
<li >Thai spices </li>
</ul>
</li>
<li>Braised Delight
<ul class="menu_list">
<li >lamb shoulder</li>
<li >cippolini onions</li>
<li >carrots</li>
<li >baby turnip</li>
<li >braising jus</li>
</ul>
</li>
<li>House Grilled Panini
<ul class="menu_list">
<li >prosciutto</li>
<li >provolone</li>
<li >avocado</li>
<li >cherry tomatoes</li>
<li >sourdough roll</li>
<li >shoestring fries </li>
</ul>
</li>
<li>House Slider
<ul class="menu_list">
<li >eggplant</li>
<li >zucchini</li>
<li >hamburger</li>
<li >balsamic vinegar</li>
<li >onion</li>
<li >carrots</li>
<li >multigrain roll</li>
<li >goat cheese</li>
</ul>
</li>
<li>Frittata
<ul class="menu_list">
<li >eggs</li>
<li >Asiago cheese</li>
<li >potatoes </li>
</ul>
</li>
<li>Coconut Soup
<ul class="menu_list">
<li >coconut milk</li>
<li >chicken</li>
<li >vegetable broth</li>
</ul>
</li>
<li>Soup Du Jour
<ul class="menu_list">
<li >grilled steak</li>
<li >mushrooms</li>
<li >vegetables</li>
<li >vegetable broth </li>
</ul>
</li>
<li>Hot and Sour Soup
<ul class="menu_list">
<li >roasted pork</li>
<li >carrots</li>
<li >Chinese mushrooms</li>
<li >chili</li>
<li >vegetable broth </li>
</ul>
</li>
<li>Avocado Rolls
<ul class="menu_list">
<li >avocado</li>
<li >whole chiles</li>
<li >sweet red peppers</li>
<li >ginger sauce</li>
</ul>
</li>
class="meat"
Упражнение
166 глава 4
решение упражнения
Найдите ингредиенты, которые должны заменяться вегетарианскими аналогами, и назначьте каждому из них соответствующий класс (fish, meat или hamburger). Если ингредиенту не ну-жен класс, оставьте строку пустой. Структура кода HTML соответствует внешнему виду меню на странице.
<li>Thai-style Halibut
<ul class="menu_list">
<li >coconut milk</li>
<li >pan-fried halibut</li>
<li >lemongrass broth</li>
<li >vegetables</li>
<li >Thai spices </li>
</ul>
</li>
<li>Braised Delight
<ul class="menu_list">
<li >lamb shoulder</li>
<li >cippolini onions</li>
<li >carrots</li>
<li >baby turnip</li>
<li >braising jus</li>
</ul>
</li>
<li>House Grilled Panini
<ul class="menu_list">
<li >prosciutto</li>
<li >provolone</li>
<li >avocado</li>
<li >cherry tomatoes</li>
<li >sourdough roll</li>
<li >shoestring fries </li>
</ul>
</li>
<li>House Slider
<ul class="menu_list">
<li >eggplant</li>
<li >zucchini</li>
<li >hamburger</li>
<li >balsamic vinegar</li>
<li >onion</li>
<li >carrots</li>
<li >multigrain roll</li>
<li >goat cheese</li>
</ul>
</li>
<li>Frittata
<ul class="menu_list">
<li >eggs</li>
<li >Asiago cheese</li>
<li >potatoes </li>
</ul>
</li>
<li>Coconut Soup
<ul class="menu_list">
<li >coconut milk</li>
<li >chicken</li>
<li >vegetable broth</li>
</ul>
</li>
<li>Soup Du Jour
<ul class="menu_list">
<li >grilled steak</li>
<li >mushrooms</li>
<li >vegetables</li>
<li >vegetable broth </li>
</ul>
</li>
<li>Hot and Sour Soup
<ul class="menu_list">
<li >roasted pork</li>
<li >carrots</li>
<li >Chinese mushrooms</li>
<li >chili</li>
<li >vegetable broth </li>
</ul>
</li>
<li>Avocado Rolls
<ul class="menu_list">
<li >avocado</li>
<li >whole chiles</li>
<li >sweet red peppers</li>
<li >ginger sauce</li>
</ul>
</li>
class=″meat"
class=″meat"class=″fish"
class=″meat"
class=″meat"
class=″hamburger"
class=″meat"
class=″meat"
дальше � 167
операции со структурой страниц в jQuery
Ñîçäàíèå êíîïîê
Предварительная подготовка в основном завершена — пора вернуться к салфетке с тре-бованиями шеф-повара. На следующем этапе вы должны создать две кнопки:
Измените разметку и сценарный код, чтобы создать две кнопки, описанные выше.
Присвойте кнопке перехода на вегетарианское меню идентификатор vegOn, а кноп-
ке восстановления меню — идентификатор restoreMe.
— Вторая кнопка должна восстанавливать меню в исходном состоянии.В д
— Кнопка «Go Vegetarian» автоматически заменяет непод-
ходящие ингредиенты веб-меню вегетарианскими аналогами.
<div class="topper">
<h2>Our Menu</h2>
<ul>
<li class="nav"> </li>
<li class="nav"> </li>
</ul>
</div>
$(document).ready(function() {
var v = false;
if (v == false){
v = true}
});//end button
if (v == true){
v = false;}
});//end button
});//end document ready
index.html
my_scripts.js
Возьми в руку карандаш
168 глава 4
решение упражнения
Измените разметку и сценарный код, чтобы создать две кнопки, описанные
выше. Присвойте кнопке перехода на вегетарианское меню идентификатор
vegOn, а кнопке восстановления меню — идентификатор restoreMe.
<div class="topper">
<h2>Our Menu</h2>
<ul>
<li class="nav"> </li>
<li class="nav"> </li>
</ul>
</div>
$(document).ready(function() {
var v = f;
if (v == false){
v = true;}
});//end button
if (v == true){
v = false;}
});//end button
});//end document ready
index.html
my_scripts.js
<button id=″vegOn">Go Vegetarian</button>
<button id=″restoreMe">Restore Menu</button>
$("button#restoreMe").click(function(){
Создание элементов button с идентификаторами vegOn и restoreMe.
С кнопками связы-вается метод click.
В уточненный селектор входит как тип, так и идентификтор элемента.
$("button#vegOn").click(function(){
Возьми в руку карандаш
дальше � 169
операции со структурой страниц в jQuery
×òî äàëüøå?
Быстро справились! Две кнопки готовы. Вычеркнем их из списка требо-ваний и перейдем к тому, что должна делать кнопка «Go Vegetarian».
Сформулируйте (своими словами) описания трех операций, которые должна выполнять кнопка перехода на вегетарианское меню.
1.
2.
3.
Нам также понадобится вторая кнопка, восста-навливающая меню в исходном состоянии.
Нам д б в
Нам нужна кнопка вегетарианского меню, которая автома-
тически подставляет вегетарианские аналоги в веб-меню.
Замена осуществляется по следующим правилам:
— у рыбных блюд аналогов нет, они просто уда-
ляются из меню;
— гамбургеры заменяются гигантскими шам-
пиньонами;
— мясные ингредиенты (кроме гамбургеров)
и яйца заменяются тофу.
Упражнение
170 глава 4
решение упражнения
1.
2.
3.
Найти элементы li класса fish и удалить соответствующие блюда из меню.
Найти элементы li класса hamburger и заменить их гигантскими шампиньо-нами.
Найти элементы li класса meat и заменить их тофу.
Начнем с первого пункта: найти элементы li класса fish и удалить их из меню. В главе 2 мы находили элементы при помощи селекторов классов и удаляли их из DOM методом remove.
jQuery также поддерживает метод detach. Оба элемента — detach и remove — удаляют элементы из DOM. Чем отличаются эти два метода и какой из них следу-ет использовать в нашей ситуации?
Не огорчайтесь, если ваши ответы получились не-много другими. Навыки перевода требований в фор-мальные описания операций приходят с практикой.
div id="top"
div class="pic_box"
img id="thumbnail"
remove detach
$("img#thumbnail").remove(); $("img#thumbnail").detach();
div id="top"
div class="pic_box"
img id="thumbnail"
Метод remove удаляет элемент из DOM.
Метод detach извлекает выбранный элемент(-ы) из DOM, но продолжает хранить, чтобы позднее его можно было вернуть на место.
Нужно изба-виться от элементов
раз и навсегда?
Временно изыму элементы из DOM
и придержу их для вас.
Вашэлемент
Сформулируйте (своими словами) описания трех операций, которые должна выполнять кнопка перехода на вегетарианское меню.
дальше � 171
операции со структурой страниц в jQuery
Напишите справа селектор и вызов remove или detach, кото-
рый приведет к показанному результату.
li
ul class="menu_list"
ul class="menu_entrees"
li class="fish"
li li li
div id="top"
div class="pic_box"
Команда jQueryРезультат в DOM
div id="news_story"
p p img
Возьми в руку карандаш
172 глава 4
решение упражнения
Напишите справа селектор и вызов remove или detach,
который приведет к показанному результату.
li
ul class="menu_list"
ul class="menu_entrees"
li class="fish"
li li li
div id="top"
div class="pic_box"
Команда jQueryРезультат в DOM
div id="news_story"
p p img
$(″div#top").remove()
Когда для элемен-та выполняется метод remove или detach, все его до-черние элементы также исключа-ются из дерева.
$(″div p").detach()
$(″li.fish").detach()
Не забывайте,что отсоединя-
ются все эле-менты, соот-ветствующие
селектору.
Группировка эле-ментов по классу или идентифика-тору упрощает их выбор.
li
p, p
Возьми в руку карандаш Решение
дальше � 173
операции со структурой страниц в jQuery
Включите строку из решения в функцию click кнопки vegOn из файла my_scripts.js. Откройте страницу в своем любимом браузере и убедитесь в том, что она работает правильно.
До выполнения $("li.fish").detach().
После выполнения $("li.fish").detach() ис-чезают все элементы с классом fish.
Метод detach определенно что-то удаляет — но не то, что мы хотели уда-лить. Мы удалили элементы из списка ингредиентов блюда, а нужно уда-лить все блюдо, имеющее вложенные элементы класса .fish.
Как приказать DOM исключить из меню все блюдо?
Мы удалили эти элементы...
…а нужноудалить все блюдо.
Тест-драйв
174 глава 4
обход дерева
В главе 1 вы узнали, что модель DOM имеет древовидную структуру. У дерева DOM есть корень, ветви и узлы. Интерпретатор JavaScript, встроенный в браузер, может обходить элементы дерева DOM (и выполнять операции с ними), причем jQuery особенно хорошо подходит для этой работы. Под «обходом дерева» понимаются перемещения вверх и вниз по дереву DOM.
Мы уже выполняли различные операции с DOM, начиная с главы 1. Примером таких операций служит только что рассмотренный метод detach (динамическое исключение элементов из DOM).
Но какие еще возможности открывает обход дерева? Чтобы понять, как работает обход, возьмем один раздел меню и представим его в виде дерева DOM.
Ïåðåìåùåíèå ïî äåðåâó DOM
li li li
ul class="menu_list"
lili class="fish"
li li li lili li li lili li
Надевайте альпинистское снаря-жение! Перемещаться по дереву DOM можно во всех направлениях: вверх и вниз, вправо и влево.
ul class="menu_list"
ul class="menu_list"
р
ul class="menu_entrees"
Чтобы подняться по дереву DOM, мы используем метод jQuery parent.
Чтобы спуститься по дереву DOM, мы используем метод jQuery children.
Для горизонтального перемещения по дереву DOM используются ме-тоды jQuery prev и next.
Методы обхода дерева DOM позволяют найти элемент и выбрать другие элементы, находя-щиеся выше, ниже или на одном уровне с ним.Давайте посмотрим, как же выбираются эти элементы.
Лазаем по дереву DOM... Очень мило. Но как это мне поможет с удалением блюд
из меню?
дальше � 175
операции со структурой страниц в jQuery
Какой из этих методов поможет убрать из меню блюда, содержащие элементы класса fish?
Ìåòîäû îáõîäà äåðåâà DOM
Чтобы объяснить DOM, что мы хотим удалить блюда, в которые входят элемен-ты класса fish, необходимо идентифицировать эти элементы по связи между ними. Методы обхода дерева jQuery предоставляют такую возможность.
$(".fish"). parent()
$(".fish"). next()$(".fish"). prev()
Дочерние элемен-ты ul.menu_list.
Родитель li.fish
Выбираем все эле-менты класса fish.
Затем переходим к элемен-ту, который находится над этими элементами.
ul class="menu_list"
li class="fish"
$(".menu_list"). children()
Выбираем все элемен-ты класса menu_list.
Затем переходим к элементам, нахо-дящимся под этими элементами.
Выбираем все эле-менты класса fish.
Затем переходим к сле-дующему элементу с тем же родителем, находя-щимся слева.
Выбираем все эле-менты класса fish.
Затем переходим к следующе-му элементу с тем же роди-телем, находящимся справа.
li li
ul class="menu_list"
li li class="fish"
li li
ul class="menu_list"
li li class="fish"
Родитель li.fish
li li
ul class="menu_list"
li li class="fish"
Мозговой
штурм
176 глава 4
долой слабые звенья!
Ñöåïëåííûå âûçîâû ìåòîäîâ
А если потребуется переместиться еще выше, ниже или глубже? Используйте сцепление методов — этот механизм по-вышает эффективность перемещения по страницам и вы-полнения операций с ними. Вот как он работает:
$(".fish").parent(). parent()
Родитель li.fish.
Чтобы подняться еще на один уровень наверх, включите еще один метод в цепочку.
Р д
ul class="menu_list"
li class="fish"
liРодитель родителя li.fish.
$(".menu_list").parent().next().remove()
Также цепочка может состоять
из разных методов.
li
li
ul class="menu_list"
ul class="menu_entrees"
Метод parent под-нимается к ро-дительскому элементу, содер-жащему выбранный элемент(-ы).
1
Метод next переме-щается к следующему элементу справа.
2
Метод remove удаля-ет элемент, к кото-рому мы перешли, из дерева DOM.
3
Первый метод parent в цепочке приводит сюда.
1
Второй метод parent в цепочке приводит сюда.
2
дальше � 177
операции со структурой страниц в jQuery
wЗагрузите страницу http://www.thinkjquery.com/chapter04/traversal/ и откройте кон-соль JavaScript в средствах разработчика вашего браузера. О средствах разработчика раз-ных браузеров рассказано в разделе «Примите к сведению» в начале книги. Выполните каждый из методов обхода со сцепленным методом detach, как показано ниже. Запиши-те, почему этот вызов поможет (или не поможет) в решении нашей задачи.Важно: Не забывайте обновлять страницу после выполнения каждой команды.
$(".menu_entrees").children().detach()
$(".fish").parent().parent().detach()
$(".fish").parent().detach()
$(".menu_list").children().detach()
Упражнение
178 глава 4
решение упражнения
Этот вызов отсоединяет элементы, дочерние по отношению к .menu_entrees. Он не подойдет для удаления блюд, содержащих рыбу, потому что он удаляет ВСЕ блюда в списке. Не то, что нам нужно...
Удаляются все блюда.
$(".menu_entrees"). children().detach()
$(".menu_list").children().detach()
Удаляются списки ингредиентов из всех блюд.
Этот вызов отсоединяет элементы, дочерние по отношению к .menu_list. Он не подойдет для удаления блюд, содержащих рыбу, потому что он удаляет ингредиенты из всех элементов ul.menu_list. Опять не то...
Загрузите страницу http://www.thinkjquery.com/chapter04/traversal/ и откройте кон-соль JavaScript в средствах разработчика вашего браузера. О средствах разработчика раз-ных браузеров рассказано в разделе «Примите к сведению» в начале книги. Выполните каждый из методов обхода со сцепленным методом detach, как показано ниже. Запиши-те, почему этот вызов поможет (или не поможет) в решении нашей задачи.Важно: Не забывайте обновлять страницу после выполнения каждой команды.
дальше � 179
операции со структурой страниц в jQuery
Этот вызов отсоединяет родительский элемент .fish. Он не подойдет для удаления блюд, содержащих рыбу, потому что он недостаточно высоко поднимается по дереву DOM. Вместо этого он удаляет эле-мент ul.menu_list (и все, что находится под ним).
Этот вызов отсоединяет родительский элемент .fish.Он делает именно то, что нам нужно.
$(".fish").parent().parent().detach()
$(".fish"). parent().detach()
Мы удалили список ингредиен-тов блюда, но не само блюдо.
То, что нужно - исчезли
только рыбные блюда.
180 глава 4
куда девались элементы?
Верно. Мы не можем просто отсоединить элементы рыбных блюд и забыть о них.Чтобы восстановление заработало, нам придется слегка доработать наш код.
li li li
ul class="menu_list"
lili class="fish"
li li li li li li li li
ul class="menu_list"
ul class="menu_list"
ul class="menu_entrees"
li class="fish"
li class="fish"
?Метод detach позволяет исключить элементы из DOM, но как вернуть их на место, когда они нам снова понадобятся?
Вызов $(".fish")parent().parent().detach() удаляет из DOM элементы трех блюд, содержащих ингредиенты класса fish.
Постойте-ка, разве мы не должны восстановить рыбные блюда в меню при
программировании второй кнопки?
Рыбные блюда должны вернуться в дерево DOM. Что для этого с ними нужно сделать?
Мозговой
штурм
дальше � 181
операции со структурой страниц в jQuery
Мы повидали уже немало конструкций jQuery и JavaScript. Какие из них нам
пригодятся для восстановления элементов класса .fish? Запишите для каж-
дой конструкции в столбце «Нужно ли использовать?» свой ответ «Да» или
«Нет» и объясните, почему вы выбрали (или не выбрали) эту конструкцию.
Один ответ мы уже записали, за вами еще три.
Нужно ли
использо-
вать?
Почему?
Завершитель Нет Завершитель — простой признак конца команды. Он не имеет отношения к восстановлению отсоединенных эле-ментов.
Переменная
Функция
Селектор
Возьми в руку карандаш
182 глава 4
решение упражнения
Нужно ли
использо-
вать
Почему?
Завершитель Нет Завершитель — простой признак конца команды. Он не имеет отношения к восстановлению отсоединенных эле-ментов.
Переменная Да Переменные используются для хранения информации. Если сохранить отсоединенные элементы в переменной, мы смо-жем их вернуть в дерево DOM, просто сославшись на пере-менную.
Функция Нет Функции выполняют операции с данными. Задача восста-новления отсоединенных элементов относится к хранению данных, а не к их обработке.
Селектор Нет Селектор выбирает элементы DOM. В нашем случае эле-менты уже выбраны, а нам нужен способ их сохранения.
В: А если я захочу избавиться от дан-ных, хранящихся в элементе, но чтобы сам элемент остался на месте?
О: Для удаления содержимого эле-мента можно воспользоваться методом empty. Например, для удаления всего текста из абзацев страницы достаточ-но выполнить следующую команду:$("p").empty();.
В: Можно ли обойти всех родителей элемента?
О: Да. Кроме метода parent, jQuery также поддерживает метод parents, об-ходящий всех родителей выбранного эле-мента. Позднее в этой главе будет приведен пример использования parents.
В: А если я хочу найти родительский элемент, ближайший к выбранному?
О: Воспользуйтесь методом closest. Как и метод parents, метод closest поднимается вверх по цепочке родителей, но останавливается при первом совпадении. Например, если вы хотите найти ближайший элемент ul над пунктом списка, используй-те команду: $("li").closest("ul").
В: Я уже знаю методы n e x t и previous, а если мне потребуется обойти все одноуровневые элементы дерева DOM?
О: К счастью, создатели jQuery преду-смотрели и такую возможность. Метод siblings обходит все элементы одного уровня с выбранным элементом.
В: Браузер Google Chrome содержит встроенную поддержку jQuery?
О: Нет. Мы можем выполнять код jQuery в средствах разработчика браузера Chrome только потому, что мы включили jQuery в страницу HTML. Если в открытой веб-странице не используется jQuery, вы не сможете выполнять команды jQuery в кон-соли JavaScript Chrome.
Возьми в руку карандаш Решение Мы повидали уже немало конструкций jQuery и JavaScript. Какие из них нам
пригодятся для восстановления элементов класса .fish? Запишите для каж-
дой конструкции в столбце «Нужно ли использовать?» свой ответ «Да» или
«Нет» и объясните, почему вы выбрали (или не выбрали) эту конструкцию.
Ниже приведен наш ответ.
частоЗадаваемые
вопросы
дальше � 183
операции со структурой страниц в jQuery
 ïåðåìåííûõ òàêæå ìîãóò õðàíèòüñÿ ýëåìåíòû
Переменные — штука весьма полезная; вот и сейчас они нам пригодятся. Вы уже встречались с переменными в первых трех главах, но тогда они использовались для хранения чисел и текстовых строк. А разве не удобно было бы хранить в перемен-ных еще и элементы DOM? Оказывается, такая возможность существует.
Браузер временно сохраняет полученные элементы в памяти. Если мы захотим воспользоваться ими позднее в своем коде, их нужно сохранить в переменной. Но как это сделать?
Интерпретатор JavaScript
DOM-версия страницы
$(".fish").parent().parent().detach();
ul class="menu_list"
lili class="fish"
li li li li li li li li
ul class="menu_list"
ul class="menu_list"
li class="fish"
lli class="fish"
li li li
Выполняется метод detach.1
Интерпретатор JavaScript при помо-щи библиотеки jQuery запрашивает у DOM нужные элементы.
2 DOM выбирает элементы и воз-вращает их интерпретатору.
3
Код jQuery
Засценой
Пожалуйста.
DOM, дай мне все эле-менты страницы с атрибутом
класса fish.
184 глава 4
знак $
$f = $(".fish").parent().parent().detach();
Знак $ в начале имени переменной указывает, что здесь хранятся элементы, полученные от jQuery.
È ñíîâà çíàê $...
Сохранить элементы совсем не сложно. Создайте переменную (как для обычных чис-ловых и текстовых данных) и присвойте ей (при помощи знака =) результат команды, возвращающей элементы. Но разве не полезно было бы с первого взгляда видеть, что в переменной хранятся специальные данные — например элементы (вместо чисел и строк)? У программистов jQuery принято начинать имена переменных, предназначен-ных для хранения возвращаемых jQuery элементов, со знака $. Тогда любой програм-мист, который будет читать ваш код, сразу поймет, что в переменной хранятся данные, полученные от jQuery.
ul class="menu_list"
lili class="fish"
li li
li li li
li li li
ul class="menu_list"
ul class="menu_list"
li class="fish"
lli class="fish"
li
li
li
$f
Конечно, хранить много элементов в одной пере-менной неудобно.Поэтому в jQuery для хране-ния элементов используются массивы JavaScript. Давайте по-смотрим, что это такое.
В переменных, которые мы использовали прежде, хранилось только одно значение. Столько раз-
ных элементов в одном контейнере? Разве это удобно?
дальше � 185
операции со структурой страниц в jQuery
Каждый раз, когда мы выбираем элементы DOM и сохраняем их в переменной, jQuery возвращает данные в виде массива. В сущности, массив — это перемен-ная с расширенными возможностями хранения данных.
Õðàíåíèå äàííûõ â ìàññèâàõ
В простой переменной хранится одно значение.
42Переменная
Хранимое значение
$a
Если весь массив на-
зывается $a, то для
обращения к отдель-
ной ячейке исполь-
зуется запись $a[n],
где n — номер ячейки
(нумерация начина-
ется с 0).
Массив
Имя пере-менной
$a[5]$a[4]$a[3]$a[2]$a[1]$a[0]
Массив представля-ет собой структу-ру данных, которая может содержать несколько переменных (как подставка содер-жит несколько про-бирок).
vВы можете сохранить и извлечь данные из любой ячейки. Например, для сохранения значения «15» в третьей ячейке используется следующая команда:
$a[2] = 15;
В массиве хранится много значений.
4 8 15 16 23 42
Третья ячейка имеет номер 2, потому что ну-мерация начинается с 0.
v
Для любознательных
Имена массивов необязательно начинать со зна-
ка доллара ($). Обозначение массивов jQuery зна-
ком $ — всего лишь распространенное правило,
принятое среди разработчиков jQuery.
186 глава 4
так аккуратно!
Õðàíåíèå ýëåìåíòîâ â ìàññèâå
$f = $(".fish").parent().parent().detach();
ul class="menu_list"
lili class="fish"
li li
li
ul class="menu_list"
lili class="fish"
li li
li
ul class="menu_list"
lili class="fish"
li li
li
Когда мы выбираем и отсоединяем элементы li и присваиваем результат опера-ции переменной ($f), jQuery берет элементы, полученные от DOM, и аккуратно сохраняет их в массиве JavaScript. А когда позднее потребуется вернуть элементы обратно в массив, эта задача будет решаться намного проще.
Каждый отсоединенный эле-мент аккуратно помещается в одну из ячеек массива $f.
jQuery берет элементы,
полученные от DOM,
и аккуратно сохраняет
их в массиве.
$f
Элементы сохраняются вместе со всем содержимым. Все элементы можно легко вернуть обратно в страницу.$f[2]$f[1]$f[0]
Р А СС Л А Б Ь Т Е С Ь
Возможности массивов этим не ограничиваются.
Но сейчас не стоит отвлекаться от основной темы. Массивы на-много подробнее рассматрива-ются в главе 6.
дальше � 187
операции со структурой страниц в jQuery
1.
2.
3.
Включите приведенную на предыдущей странице строку кода, которая отсоеди-няет родителей элементов #fish, в функцию-обработчик click кнопки vegOn в файле my_scripts.js. Затем откройте страницу в своем любимом браузере и убе-дитесь в том, что все правильно работает.
Получилось! Давайте сверимся со списком.
Итак, следующая задача — найти блюда, в состав которых входят гам-бургеры, и заменить гамбургеры гигантскими шампиньонами.
То, чего мы хотели:
рыбные блюда исключены
из меню.
Мы уже умеем исключать элементы из DOM, но как динами-чески заменить содержимое DOM другим содержимым?
Найти элементы li класса fish и удалить соответствующие блюда из меню.Найти элементы li класса hamburger и заменить их гигантскими шампиньонами.Найти элементы li класса meat и заменить их тофу.
Тест-драйв
Мозговой
штурм
188 глава 4
шило на мыло
...и ставлю на его место что-то
другое.
Èçìåíåíèå ýëåìåíòîâ ìåòîäîì replaceWith
Метод replaceWith позволяет заменить выбранные элементы новыми эле-ментами. Когда вам потребуется провести подобную замену в DOM, исполь-зуйте этот удобный метод jQuery. Допустим, вы хотите динамически заменить элемент заголовка 2-го уровня с текстом «Our Menu» заголовком 1-го уровня с текстом «My Menu». Вот как это делается методом replaceWith:
$("h2").replaceWith("<h1>My Menu</h1>");
Выбираем все элементы h2.
Заменяем выбранные элементы...
…содержимым, заключенным в скобки.
Интерпретатор JS находит эле-мент заголовка 2-го уровня…
1 …и заменяет его содержимым в круглых скобках. В модели DOM появляется новый элемент и новое содержимое.
2
h2
body
<h1>My Menu</h1>
body
h1
Я забираю выбранный эле-мент из DOM...
дальше � 189
операции со структурой страниц в jQuery
li class="hamburger"
ul class="menu_list"
Напишите код, который находит элементы li класса hamburger и заменяет их элемен-тами li класса portobello. Следующая схема поможет вам лучше представить суть задачи. Мы уже написали часть решения за вас; допишите остальное.
?Код, который вы напишете здесь…
li class="hamburger"
li class="portobello"
ul class="menu_list"
ul class="menu_list"
То, что за-меняется.
То, что долж-но остаться после замены.
×åì ïîìîæåò replaceWith?
Итак, мы должны найти элементы li класса hamburger и заменить их элементами li класса portobello. Но прежде чем браться за про-граммирование, стоит лишний раз подумать над задачей.
$( ).replaceWith( <em>Portobello Mushroom</em> );
Так должна вы-глядеть страница после замены.
...должен де-лать это.
Упражнение
190 глава 4
решение упражнения
Включите вызов replaceWith в функцию click кнопки vegOn в фай-ле my_scripts.js. Откройте страницу в своем любимом браузере и нажмите кнопку «Go Vegetarian». Убедитесь в том, что все работает правильно.
Гамбургеры заменены шампиньонами.
li class="hamburger"
ul class="menu_list"
Напишите код, который находит элементы li класса hamburger и заменяет их эле-ментами li класса portobello. Следующая схема поможет вам лучше понять суть задачи. Вот как выглядит наше решение:
?$( ).replaceWith( <em>Portobello Mushroom</em> );″.hamburger″ ″<li class=‘portobello’> </li>″
Выбираем все элементы класса hamburger.
Метод replaceWith динамически заменяет выбранное содер-
жимое элементом в круглых скобках. Главное — помнить,
что круглые скобки могут содержать код HTML.
Тест-драйв
дальше � 191
операции со структурой страниц в jQuery
Что там следующее в нашем списке?
Íå òîðîïèòåñü ñ replaceWith
Нужно найти элементы класса meat и заменить их элементами класса tofu.
li class="meat"
ul class="menu_list"
li class="tofu"
Вообще-то на этот раз replaceWith не подойдет.
Это же просто! Снова используем replaceWith,
верно?
Метод jQuery replaceWith — простой и мощ-ный инструмент. Но, к сожалению, для решения этой задачи он не подходит. Почему?
Мозговой
штурм
1.
2.
3.
Найти элементы li класса fish и удалить соответствующие блюда из меню.Найти элементы li класса hamburger и заменить их гигантскими шампиньонами.Найти элементы li класса meat и заменить их тофу.
192 глава 4
неоднозначная замена
Êîãäà replaceWith íå ïîäõîäèò
Метод replaceWith хорошо подходит для вы-полнения замены типа «один к одному» — на-пример, замены класса hamburger классом portobello.
Замена «многие к одному»Çàìåíà «ìíîãèå ê îäíîìó»
Однако сценарий замены в следующем пункте нашего списка задач не относит-ся к типу «один к одному». Мы должны заменить много разных видов ингреди-ентов (индейка, яйца, говядина, отбив-ные и т. д.) одним ингредиентом (тофу).
Замена «один ко многим»Çàìåíà «îäèí êî ìíîãèì» Да, мы можем взять элемен-ты класса meat и заменить их все на tofu.
Но когда позднее потребуется выбрать тофу и восстановить старыми элемента-ми, возникает проблема. Модель DOM о них уже не помнит!
Тофу можно заменить одним типом мяс-ных ингредиентов, но это совсем не то, что нам нужно.
Таким образом, замену придется выпол-нять в два этапа.
Позднее DOM уже ничего не помнит о разных типах мясных ингреди-ентов.
Вставить элементы li класса tofu в DOM после элементов meat.
1
Отсоединить элементы класса meat и сохранить их в переменной.
2
Замена «один к одному»
???? ??
дальше � 193
операции со структурой страниц в jQuery
Âñòàâêà HTML â DOM
Вставить элементы li класса tofu в DOM после элементов meat.
1
Отсоединить элементы класса meat и сохранить их в переменной.
2
До настоящего момента мы занимались либо удалением, либо заменой элементов DOM. К счастью, создатели библиотеки jQuery также предоставили различные средства встав-ки в DOM. Мы рассмотрим два метода вставки: before и after.
Метод before вставляет содержимое перед выбранным элементом:
Метод after вставляет содержимое после выбранного элемента.
$(".meat").before("<li>Tofu</li>");
$(".meat").after("<li>Tofu</li>");
Напишите код jQuery, реализующий два этапа нашего решения.
ul class="menu_list"
lili class="meat"
li lili
ul class="menu_list"
li class="meat" li
Возьми в руку карандаш
194 глава 4
решение упражнения
Для кнопки переключения на вегетарианское меню выполнены все пункты списка.
Пора переходить к кнопке восстановления меню. Список задач для этой кнопки выглядит так:
найти шампиньоны в ингредиентах и заменить их гамбургерами;
найти тофу в ингредиентах и заменить его различными видами мясных ингредиентов (в правильном порядке).
вернуть рыбные блюда в меню (например, перед первым элементом меню в левом столбце);
Что же необходимо сделать для решения первой задачи?
С использованием before все понятно, но как задать первого потомка?
<li> Braised Delight</li>
ul class="menu_list"
ul class="menu_list"
ul class="menu_entrees"
div class= "left_col"
<li> Grilled Panini</li>
Нужно заново присо-единить рыбные блюда к этому элементу…
…перед первым потомком.
Вставить элементы li класса tofu в DOM после элементов meat.
1
Отсоединить элементы класса meat и сохранить их в переменной.
2
Напишите код jQuery, реализующий два этапа нашего решения.
$(“.meat”).after(“<li class=‘tofu’><em>Tofu</em></li>”);
$m = $(“.meat”).detach();
1.
2.
3.
Найти элементы li класса fish и удалить соответствующие блюда из меню.
Найти элементы li класса hamburger и заменить их гигантскимишампиньонами.
Найти элементы li класса meat и заменить их тофу.
Возьми в руку карандаш Решение
дальше � 195
операции со структурой страниц в jQuery
Ôèëüòðû (÷àñòü 1)
К счастью, в jQuery существуют фильтрующие методы (или просто фильтры), которые позво-ляют сократить выбранное множество элементов для решения таких задач, как поиск первого потомка. Мы рассмотрим шесть фильтров (три на этой странице, три на следующей).
firstМетод first исключает из выбранного множества все элементы, кроме первого.
eqМетод eq исключает из выбранного множества все элементы, кроме элемента, индекс которого равен числу в круглых скобках.
lastМетод last исключает из выбранного множества все элементы, кроме последнего.
Давайте посмотрим, как работают фильтры, на примере одного эле-мента нашего меню:
$(".menu_list").children().last();$(".menu_list").children().first();
lili class="meat"
li li
li
ul class="menu_list"
li
$(".menu_list").children().eq(0);
lili class="meat"
li li
li
ul class="menu_list"
li
$(".menu_list").children().eq(1);
$(".menu_list").children().eq(2);
$(".menu_list").children().eq(3);
$(".menu_list").children().eq(4);
Метод first сокращает выбранное множество до первого элемента.
Метод last сокращает
выбранное множество
до последнего элемента.
Метод eq сокращает
выбранное множество
до элемента, индекс ко-
торого задан в круглых
скобках.
Вспомните, что jQuery воз-
вращает выбранные элемен-
ты в виде массива. Индекс,
передаваемый методу eq,
соответствует ячейке эле-
мента в массиве.
0
01
12
23
3
4
4
196 глава 4
уточнение выбора
Теперь посмотрим, что собой представляют методы slice, filter и not.
filterslice notМетод slice оставляет в выбран-ном множестве только те эле-менты, индексы которых лежат в диапазоне, заданном в круглых скобках.
Метод filter оставляет в выбранном множестве толь-ко те элементы, которые соот-ветствуют селектору в круглых скобках.
Метод not исключает из вы-бранного множества все эле-менты, не соответствующие селек-тору в круглых скобках.
Метод slice сокращает выбран-ное множество до диапазона, границы которого передаются при вызове.
Метод filter сокращает выбран-
ное множество до подмножества,
определяемого селектором в кру-
глых скобках.
lili class="meat"
li li
ul class="menu_list"
li
01 2 3 4
$(".menu_list").children().slice(1,3);
$(".menu_list").parents().filter(".organic");
Метод not сокращает выбранное мно-жество до элементов, не соответству-ющих селектору в круглых скобках.
lili class="local"
li
ul class="menu_list organic"
li
$("ul.menu_list.organic").children().not(".local");
Какой из этих элементов поможет нам определить первого потомка меню?
Методы filter и not позволяют использовать селекторы для определения подмно-жеств выбранного множества. Селектор передается в аргументе при вызове метода.
li class="local"
ul class="organic"
Методы filter и not хорошо работа-
ют в сочетании с методами parents
и children.
Метод parents позволяет полу-чить все элементы, которые являются родителями и пред-ками более высокого уровня для выбранного элемента.
В этом примере будет воз-
вращен только один эле-
мент — второй элемент li.
Ôèëüòðû (÷àñòü 2)
дальше � 197
операции со структурой страниц в jQuery
Стань DOMПредставьте себя на месте дерева DOM. Соедините команды jQuery
с элементом(-ами), которые будут выбраны при их выполнении.
Считайте, что страница не содержит других элементов. Ответ
для первой команды мы написали за вас.
body
h4
li
li lili li
ul class="menu_list"
ul class="menu_entrees"
div class="left_col"
div class="menu_wrapper"
li li
li lili lili lili li
ul class="menu_list"
ul class="menu_list"
$(".menu_list").parents().filter("div");
$("li").first();
$(".left_col").children().not("h4");
$(".menu_list li").eq(3); $(".menu_list").children().last();
$(".menu_list").parent().slice(1,3);
Напишите строку кода jQuery, которая вернет рыбные блюда в меню
(например, перед первым элементом, вложенным в menu_entrees).
.before($f);
Возьми в руку карандаш
198 глава 4
решение упражнения
Стань DOM. РешениеПредставьте себя на месте дерева DOM. Соедините команды jQuery
с элементом(-ами), которые будут выбраны при их выполнении.
Считайте, что страница не содержит других элементов. Ответ
для первой команды мы написали за вас.
li
li lili li
ul class="menu_list"
ul class="menu_entrees"
li li
li lili lili lili li
ul class="menu_list"
ul class="menu_list"
$(".menu_list").parents().filter("div");
$("li").first();
$(".menu_list li").eq(3); $(".menu_list").children().last();
Напишите строку кода jQuery, которая вернет рыбные блюда в меню
(например, перед первым элементом, вложенным в menu_entrees).
.before($f);
body
h4
div class="left_col"
div class="menu_wrapper"
$(".left_col").children().not("h4");
$(".menu_list").parent().slice(1,3);
$(".menu_entrees li").first()
Возьми в руку карандаш Решение
дальше � 199
операции со структурой страниц в jQuery
Итак, первое требование в списке кнопки восстановления меню реализовано. Осталось еще два.
Âåðíèòå ãàìáóðãåð íà ìåñòî
Помните это упражнение? Сейчас мы проделаем его в обратном порядке. Напишите код, который находит элементы li класса portobello и заменяет их элементами li класса hamburger. Следующая схема поможет вам лучше представить суть задачи. Мы уже на-писали часть решения за вас; допишите остальное.
Следующая задача кажется смутно знакомой, не правда ли? По сути, мы долж-ны проделать исходную замену в обратном порядке. Почему? Да потому что мы имеем дело с заменой «один к одному», а такие замены хороши своей логиче-ской простотой.
Хочу обратно...
Найти шампиньоны в ингредиентах и заменить их гамбургерами.
Найти тофу в ингредиентах и заменить его различными видами мясных ингредиентов (в правильном порядке).
Вернуть рыбные блюда в меню (например, перед первым элементом меню в левом столбце).
Замена «один к одному»
li class="portobello"
ul class="menu_list"
?Код, который вы напишете здесь…
…должен делать это.
$( ). replaceWith( Hamburger );
Упражнение
200 глава 4
решение упражнения
È ãäå æå ìÿñî?
Вспомните, что мы сделали с элементами li.meat? Давайте посмотрим:
Мы подошли к последнему пункту списка восстановления меню.
Затем мы отсоединили элементы li.meat, но сохранили их в $m.
$(".meat").after("<li class='tofu'><em>Tofu</em></li>");
$m = $(".meat").detach();
Элементы li.tofu были вставлены в DOM за элементами meat.
Так где взять эти элементы и как вернуть их на место?
Всего одна короткая строка с replaceWith — и гамбургеры вернулись на место! Отличная работа!
li class="portobello"
ul class="menu_list"
?$( ).replaceWith( Hamburger );
Выбираем все элемен-ты класса portobello. Метод replaceWith динамически заменяет выбранное содержимое элементом в круглых скобках.
".portobello" "<li class='hamburger'> </li>"
Найти шампиньоны в ингредиентах и заменить их гамбургерами.
Найти тофу в ингредиентах и заменить его различными видами мясных ингредиентов (в правильном порядке).
Вернуть рыбные блюда в меню (например, перед первым элементом меню в левом столбце).
дальше � 201
операции со структурой страниц в jQuery
Ìàññèâ îòñîåäèíåííûõ ýëåìåíòîâ
$m
Вспомните, что при хранении элементов jQuery мы начинаем имя перемен-ной со знака $, который показывает, что в переменной хранятся специальные данные. В нашем случае переменная содержит массив jQuery, в котором эле-менты $m хранятся следующим образом:
<li class="meat">
lamb shoulder</li>
<li class="meat">
proscuttio</li>
<li class="meat">
eggs</li>
<li class="meat">
chicken</li>
<li class="meat">
chicken</li>
<li class="meat">
chicken</li>
Каждый элемент li.meat…
…хранится в от-дельной ячейке…
…массива $m.
$m[2]$m[1]$m[0] $m[3] $m[4] $m[5]
Нужно вернуть на место каждый элемент li.meat, заменив им элемент li.tofu. Мы уже видели много методов, встав-ляющих элементы в DOM. Какой метод вы выбрали бы для этой задачи?
Мозговой
штурм
202 глава 4
возвращение each
В главе 3 было показано, как использовать метод each для перебора элементов мас-сива. Сейчас мы снова воспользуемся этим методом для перебора всех элементов meat в массиве $m и их возвращения на исходные места. Но для этого необходимо поближе познакомиться с тем, как работает метод each.
$(".tofu").each(function(i){
$(this).after( );
});
Переменная i отсчитывает обработанные элементы (нумерация начинается с 0).
Метод each последова-тельно обрабатывает элементы массива, выпол-няя некоторую операцию с каждым элементом.
Для ссылки на теку-щий обрабатываемый элемент использу-ется запись $(this).
Здесь используется метод after,
но для обработки массива элемен-
тов можно использовать любой
метод jQuery.
Ìåòîä each è ïåðåáîð ìàññèâîâ
jQuery сохраняет результаты вы-бора в массиве.
Мы хотим вставить элемент meat после каждого элемента li.tofu.Что должно быть написано в скобках?
Метод each наглядно
демонстрирует мощь
сценариев jQuery: с его
помощью можно последо-
вательно обрабатывать
элементы массива.
$m
i = 0
Настоящая сила метода each проявляется при включении в него функции. Эта функция последовательно выполняет некоторую операцию с каждым перебираемым элементом.
Метод each напоминает
станок на конвейере.
Ключевым словом this обозначается элемент,
с которым работает функция.
Индекс отслеживает эле-
мент, с которым рабо-
тает функция.
дальше � 203
операции со структурой страниц в jQuery
Разложите магниты в правильном порядке, чтобы они образовали правиль-
ный код функции-обработчика кнопки restoreMenu. Несколько магнитов
уже находятся на своих местах.
$(".tofu").each( function(i){
.before($f);
$(".menu_entrees li").first()
});
$(".portobello").replaceWith(
$(".tofu").remove();
$m[i]);
$(this).after(
"<li class='hamburger'>Hamburger</li>");my_scripts.js
$("button#restoreMe").click(function(){
}
});
if (v == true){
v = false;
Развлечения с магнитами
204 глава 4
решение упражнения
Разложите магниты в правильном порядке, чтобы они образовали правиль-
ный код функции-обработчика кнопки restoreMenu. Несколько магнитов
уже находятся на своих местах.
my_scripts.js
$("button#restoreMe").click(function(){
$(".tofu").each( function(i){
.before($f);.b$(".menu_entrees li").first()
}
});
});
$(".portobello").replaceWith(
$(".tofu").remove();
$m[i]);
if (v == true){
v = false;
$$(this).after(
"<li class='hamburger'>Hamburger</li>");
Чтобы вернуть на место элементы
meat, мы указываем имя массива $m
и индекс, соответствующий элемен-
ту tofu, с которым в данный момент
работает функция.
Развлечения с магнитами. Решение
дальше � 205
операции со структурой страниц в jQuery
Âðîäå… âñå?
Мы выполнили все, что требовалось для кнопки восстановления меню. Давайте обновим файлы, и проект можно считать завершенным.
Да, вы абсолютно правы.
К счастью, веб-дизайнер уже включил класс veg_leaf в файл my_style.css. Вот как он выглядит:
Постойте, мы забылипро постскриптум...
.veg_leaf{
list-style-image:url('../images/leaf.png');
}
my_style.css
Напишите команду, которая назначает класс veg_leaf родителю ро-дителя элемента класса tofu.
Найти шампиньоны в ингредиентах и заменить их гамбургерами.
Найти тофу в ингредиентах и заменить его различными видами мясных ингредиентов (в правильном порядке).
Вернуть рыбные блюда в меню (например, перед первым элементом меню в левом столбце).
P.S. И еще хотелось бы, чтобы замененные
вегетарианские блюда в меню были помече-
ны — например зеленым листом.
Подсказка: в этом вам поможет addClass.
Упражнение
206 глава 4
решение упражнения
$(".tofu").parent().parent().addClass("veg_leaf");
В: С другими фильтрами все понятно, но от slice у меня до сих пор голова идет кругом. Можно объяснить подроб-нее?
О: Метод slice действительно непрост. Больше всего сложностей возникает с его параметрами: slice(start, end).
Первый параметр — start — является обязательным; без него slice работать не будет. Параметр start указывает, с какого индекса начинается выделяемый диапазон. Помните, что у первого элемента массива индекс равен 0. Параметр start также может принимать отрицательные значения. В этом случае slice отсчитывает значе-ния от конца, а не от начала массива.
В: А что делает параметр end метода slice?
О: Второй параметр метода slice — end — не является обязательным. Если он отсутствует, то slice начинает от позиции, заданной параметром start, и выбирает все элементы с индексами, большими start. Если забыть о том, что индексы элементов массива начинаются с 0, смысл параметра end может быть неочевидным.
В: Похоже, метод each способен на многое. А как each узнает, с каким эле-ментом он работает?
О: Настоящая сила each проявляется в сочетании с ключевым словом this. Ме-тод each автоматически отслеживает зна-чение индекса и «знает», с каким элементом он работает. Используйте each только при выборе нескольких элементов. Для об-ращения к текущему элементу используйте ключевое слово this, но заключите его в сокращенную форму jQuery: $(this).
В: Почему мы включаем «i» или «index» в каждую функцию each?
О: Индексная переменная, которой обыч-но присваивается имя «i» или «index», ис-пользуется функцией each для отслежива-ния элемента, с которым работает функция. При помощи этой переменной each опреде-ляет, когда перебор завершен, а обработку следует прекратить.
В: Как провести поиск элементов в мас-сиве jQuery?
О: Для поиска элементов в массиве jQuery используется метод find. Допустим, у нас
имеется массив элементов li в массиве jQuery: var $my_elements = $("li");Чтобы найти в этом массиве все якорные элементы, используйте следующую коман-ду: $my_elements.find("a"); В: Позволяет ли jQuery заключить эле-мент внутри другого элемента?
О: Да, позволяет. Допустим, изображение с дентификатором oreilly нужно за-ключить внутри якорного элемента. Это де-лается так:
$("img#oreilly").wrap("<a href='http://www.oreilly.com'></a>");
Пара перемещений по DOM, немного магии addClass — и дело сделано!
частоЗадаваемые
вопросы
дальше � 207
операции со структурой страниц в jQuery
Здорово! Наши клиенты в восторге от веб-меню, а самое замечательное, что
нам не приходится вести две разных версии меню. Вся информация на одной
странице!
С тех пор как мы в последний раз обновляли файлы, прошло уже нема-ло времени. Добавьте код кнопки восстановления меню, а также код до-бавления/удаления класса veg_leaf для блюд с вегетарианскими ана-логами. Также вы всегда можете загрузить файлы этой главы по адресу http://www.thinkjquery.com/chapter04/ и сравнить их со своим кодом.
Лист появился из-за добав-
ления класса veg_leaf.
Теперь у Александры будет
меньше хлопот с сопрово-
ждением сайта — и у нее
появится время для приго-
товления новых блюд.
Тест-драйв
208 глава 4
ваш инструментарий jquery
Массивы
В массивах jQuery может хра-
ниться любая информация
(в том числе и элементы).
Как и в случае с переменными,
перед именем массива принято
ставить знак $, который пока-
зывает, что в массиве хранятся
специальные данные jQuery.
Âàø èíñòðóìåíòàðèé jQuery
Глава 4 осталась позади, а ваш творческий арсенал расширился: в нем появились средства обхода и выполнения операций с DOM, массивы и фильтры.
Обход DOM
Перемещение по дереву DOM
для выполнения различных опе-
раций.
Для перехода к нужной позиции
дерева используются отно-
шения между элементами и
различные методы (например,
parent и child).
Сцепленные вызовы методов
эффективны для быстрого
перемещения по дереву DOM.
Операции с DOM
Вы можете выполнять операции
добавления, замены и удален
ия
элементов из DOM:
detach
remove
replaceWith
before
after
ФильтрыФильтры предназначены для со-кращения множества выбранных элементов:first
equal
last
slice
filter
not
ГЛА
ВА 4
jQuery эффекты и анимация5
Плавно и изящно
Реализация всяких интересных возможностей — дело замечатель-ное, но если ваша страница не будет хорошо смотреться, люди не станут при-ходить на сайт. И здесь на первый план выходят визуальные эффекты и ани-мация jQuery. Вы научитесь организовывать переходы, скрывать и отображать нужные части элементов, изменять размеры элементов на странице — и все это на глазах у ваших посетителей! Вы научитесь планировать выполнение анимаций, чтобы они происходили с различными интервалами, отчего ваша страница будет выглядеть исключительно динамично.
Взгляните, как я умею двигаться; я так грациозна.
Спорим, вы так не сможете!
210 глава 5
только без flash
Фирма DoodleStuff поставляет детям принадлежности для рисования. Несколько лет назад фирма открыла популярный веб-сайт с интерактивными приложениями для де-тей. Популярность фирмы стала расти настолько быстро, что она не успевает справ-ляться с пожеланиями своих клиентов.
Ориентируясь на новую, более широкую аудиторию, руководитель веб-проектов хочет создать приложение, которое не потребует установки Flash или других дополнитель-ных модулей для браузеров.
Детские проекты должны быть веселыми и простыми. Сможете создать приложе-ние для детей в возрасте от 6 до 10 лет? Не забудьте про визуальные эффекты и взаимодействие с пользователем.
Только, пожалуйста, без Flash!
Íîâûé çàêàç
дальше � 211
jquery эффекты и анимация
Ïðîåêò «Ñîáåðè ìîíñòðà»
Перед вами схема нового проекта, которую вам дал руководитель веб-проектов, а также переданные веб-дизайнером графические файлы.
У вас имеется подробное описание требований и необходимые графические файлы, но нет разметки HTML и кода CSS — с этого и следует начинать. Что для этого необходимо?
frame.pngширина: 545 пикселоввысота: 629 пикселов
Проект «Собери монстра»Развлекательное приложение «Собери монстра» адресовано детям конкретной возрастной группы. Оно позво-ляет «собрать» изображение монстра из 10 разных вариантов головы, глаз, носа и рта. Выбор частей монстра должен сопровождаться анимацией.
Модель изменения лица монстра
Графические файлы
Пользовательский интерфейс Анимация
После девяти щелчков каждая полоса должна «перематываться» к началу.
Модель анимации с молниями
Изображения должны проявляться и быстро исчезать, имитируя сверкание молнии.
headsstrip.png ширина: 3670 пикселов, высота: 172 пикселов
eyessstrip.png ширина: 3670 пикселов, высота: 79 пикселов
nosessstrip.png ширина: 3670 пикселов, высота: 86 пикселов
mouthsstrip.png ширина: 3670 пикселов, высота: 117 пикселов
lightning_01.jpg
lightning_02.jpg
lightning_03.jpg
Область головы
Область глаз
Область носа
Область рта
Рамка
Контейнерimg - lightning1
img - lightning2
img - lightning3
Щелкните, чтобы изменить голову монстра.
Щелкните, чтобы изменить глаза монстра.
Щелкните, чтобы изменить нос монстра
Щелкните, чтобы изменить рот монстра.
212 глава 5
закладываем фундамент
Мы уже неоднократно говорили о том, как важно тщательно продумать структуру и стиль приложения до перехода к программированию. В данном случае это еще важнее — если не позаботиться о правиль-ном расположении всех визуальных элементов, с эффектами и анимацией очень скоро начнутся пробле-мы. Нет ничего противнее, чем глазеть в свой код jQuery и ломать голову над тем, почему же он не рабо-тает так, как нужно вам. Лучше заранее построить эскиз приложения и поразмыслить над тем, что будет происходить на экране.
Ìàêåò è ïîçèöèîíèðîâàíèå
Здесь должна быть область div с ши-риной 545 пикселов для рамки…
…и область div шириной 367 пикселов для изобра-жения лица монстра.
Ширина 367 пикселов
Какой атрибут CSS позволит нам это сделать?
Ширина каждой полосы 3670 пик-селов, но на экране отображаются только 367 пикселов.
div#frame
div#pic_box
div#head
div#eyes
div#nose
div#mouth
Высота 172 пиксела
Высота 79 пикселов
Высота 117 пикселов
Высота 86 пикселов
Полосы изображений размещаются в элемен-тах img, вложенных в область div соответ-ствующей части лица монстра. Например, тег img для headsstrip.jpg будет находиться внутри div#head.
Лицо монстра складывается еще из четы-рех областей div, и в каждой отображается часть одной из полос.
дальше � 213
jquery эффекты и анимация
Запишите в пустых местах файлов HTML и CSS идентификатор CSS, свойство или зна-чение, обеспечивающее нужное размещение элементов приложения «Собери монстра». Если сомневаетесь, перечитайте две предыдущие страницы. Мы заполнили несколько пропусков за вас.
body><header id="top"><img src="images/Monster_Mashup.png" /><p>Make your own monster face by clicking on the picture.</p></header> <div id="frame"> <div id= > <div id= class="face"><img src="images/headsstrip.jpg"></div> <div id= class="face"><img src="images/eyesstrip.jpg"></div> <div id= class="face"><img src="images/nosesstrip.jpg"></div> <div id= class="face"><img src="images/mouthsstrip.jpg"></div> </div></div> <script type="text/javascript" src="scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript" src="scripts/my_scripts.js"></script></body>
#frame { position: left:100px; top:100px; width:545px; height:629px; background-image:url(images/frame.png); z-index: 2; overflow:}
#pic_box{ position: left:91px; top:84px;
height:460px; z-index: 1; overflow:}
.face{ position: left:0px; top:0px; z-index: 0;}
#head{
}
#eyes{
}
#nose{
}
#mouth{
}
index.html
my_style.css
relative;
"pic_box"
height:172px;
Упражнение
214 глава 5
решение упражнцения
Запишите в пустых местах файлов HTML и CSS идентификатор CSS, свойство или значе-ние, обеспечивающее нужное размещение элементов приложения Monster Mashup. Если засомневаетесь, просмотрите еще раз две предыдущие страницы. Мы заполнили несколько пропусков за вас.
body><header id="top"><img src="images/Monster_Mashup.png" /><p>Make your own monster face by clicking on the picture.</p></header>
<div id="frame"> <div id= > <div id= class="face"><img src="images/headsstrip.jpg"></div> <div id= class="face"><img src="images/eyesstrip.jpg"></div> <div id= class="face"><img src="images/nosesstrip.jpg"></div> <div id= class="face"><img src="images/mouthsstrip.jpg"></div> </div></div> <script type="text/javascript" src="scripts/jquery-1.6.2.min.js"></script> <script type="text/javascript" src="scripts/my_scripts.js"></script></body>
#frame { position: left:100px; top:100px; width:545px; height:629px; background-image:url(images/frame.png); z-index: 2; overflow:}
#pic_box{ position: left:91px; top:84px; height:460px; z-index: 1; overflow:}
.face{ position: left:0px; top:0px; z-index: 0;}
#head{
}
#eyes{
}
#nose{
}
#mouth{
}
index.html
my_style.css
relative;
"pic-box"
height:172px;
absolute;
hidden;
Присваивание overflow
значения hidden по-
зволяет скрыть часть
полосы изобра жения,
выходящую за границы
области pic_box.
relative;
height:79px;
height:86px;
height:117px;
hidden;
width:367px;
"head""eyes""nose""mouth"
При анимации позиции элемен-та используется абсолютное или относительное по-зиционирование.
Для этого также можно воспользо-ваться свойством CSS clip.
дальше � 215
jquery эффекты и анимация
index.html
my_style.css
Далее необходимо разобраться со структурными изменениями в файлах HTML и CSS. Включите приведенный ниже код в файлы index.html и my_style.css. Графи-ческие файлы можно загрузить по адресу www.thinkjquery.com/chapter05.
<div id="container"> <img class="lightning" id="lightning1" src="images/lightning-01.jpg" /> <img class="lightning" id="lightning2" src="images/lightning-02.jpg" /> <img class="lightning" id="lightning3" src="images/lightning-03.jpg" /> <div id="frame"> <div id="pic_box"> <div id="head" class="face"><img src="images/headsstrip.jpg"></div> <div id="eyes" class="face"><img src="images/eyesstrip.jpg"></div> <div id="nose" class="face"><img src="images/nosesstrip.jpg"></div> <div id="mouth" class="face"><img src="images/mouthsstrip.jpg"></div> </div> </div></div>
Åùå íåìíîãî ñòðóêòóðû è ñòèëÿ
#container{ position:absolute; left:0px; top:0px; z-index: 0;}
.lightning{ display:none; position:absolute; left:0px; top:0px; z-index: 0;}
body{
background-color:#000000;
}
p{
color:#33FF66;
font-family: Tahoma, Verdana, Arial, Helvetica, sans-serif;
font-size:12px;
}
#text_top {
position:relative;
z-index: 4;
}
Задание!
Чтобы использовать анимацию для элемен-та, следует задать его свойству position значение absolute, fixed или relative.
В исходном состоянии молнии должны быть невидимы.
Добавляем контейнер и вкладываем в него изображение с молниями.
216 глава 5
для экспертов по щелчкам
Пользовательский интерфейс
После девяти щелчков каждая полоса должна «перематываться» к началу.
Область головы
Область глаз
Область носа
Область рта
Рамка
Контейнерimg - lightning1img - lightning2img - lightning3
Щелкните, чтобы изменить голову монстра.
Щелкните, чтобы изменить глаза монстра.
Щелкните, чтобы изменить нос монстра.
Щелкните, чтобы изменить рот монстра.
Итак, мы разобрались с визуальным макетом приложения «Собери монстра». Давайте проработаем интерактивную часть пользовательского интерфейса, представленную в эскизе. Нам предстоит запрограммировать реакцию раз-ных элементов страницы на щелчки. Собственно, этим мы занимаемся уже четыре главы, так что сейчас это уже пара пустяков.
Ïðîðàáîòêà èíòåðôåéñà
Нужно проверять
каждый щелчок,
чтобы при дости-
жении конца полосы
«перемотать» ее
к началу.
Щелчок в каждой области прокру-чивает полосу изображений.
В: Что это за свойство CSS position? Почему оно необходимо для анимации и эффектов jQuery?
О: Свойство CSS position управляет тем, где и как браузерный движок размещает элементы. Многие эффекты jQuery реализу-ются с использованием свойства position. Если вы забыли, как работает это свойство, обращайтесь к превосходному объясне-нию в центре для разработчиков Mozilla:
http://developer.mozilla.org/en/CSS/position#Relative_positioning
В: Почему для анимации элементов свойству CSS position необходимо за-дать значение absolute, fixed или relative ?
О : Если оставить свойству CSS position значение по умолчанию (т. е. static), то для элемента будет невоз-можно задать позицию сторон (top, right, left и bottom). При использовании функции animate возможность измене-ния этих позиций необходима, а в режиме static это невозможно. Со значениями absolute, fixed и relative — такой проблемы нет.
В: Вы упомянули какой-то «браузер-ный движок». А это что такое?
О: Браузерный движок визуализации — один из важнейших компонентов браузера, который интерпретирует разметку HTML и код CSS и отображает результат в окне просмотра браузера. Google Chrome и Safari используют движок визуализации Webkit; Firefox использует Gecko, а Microsoft Internet Explorer — движок, который назы-вается Trident.
частоЗадаваемые
вопросы
дальше � 217
jquery эффекты и анимация
Расставьте магниты в правильном порядке, чтобы элемент div#head реагировал
на щелчки. Проследите за тем, чтобы переменные и условные конструкции сле-
довали в правильном порядке для обнаружения девятого щелчка.
$(document).ready(function(){
$("#head").click(function(){
if (headclix
});
});
var headclix
< 9){
headclix
else {
headclix
}
}
= 0;
+= 1;
= 0;
Развлечения с магнитами
218 глава 5
решение упражнения
Конечно, можно! Все элементы работают по той же схеме, что и элемент div#head (с небольшими изменениями вро-де имени переменной).
Расставьте магниты в правильном порядке, чтобы элемент div#head реагировал
на щелчки. Проследите за тем, чтобы переменные и условные конструкции следо-
вали в правильном порядке для обнаружения девятого щелчка.
$(document). ready(function(){
$("#head").click(function(){
if (headclix
});
});
var headclix = 0;
+= 1;
< 9){
headclix
В исходном состоянии пере-менная равна 0, потому что
щелчков еще не было.
else {
headclix = 0;
}
}
Условие ограничивает пользователя девятью щелчками.
Значение переменной headclix
увеличивается на 1.
Здесь будет размещаться код анимации.
Здесь будет размещаться код «перемотки» полосы изображений.
После девятого щелчка переменной headclix воз-вращается значение 0.
Если значение headclix больше либо равно 9, сделать следу-ющее:
Нельзя ли повторно использовать этот код для обработки
щелчков на других областях?
Развлечения с магнитами. Решение
дальше � 219
jquery эффекты и анимация
$(document).ready(function(){
$("#head").click(function(){ if (headclix < 9){ headclix += 1; } else{ headclix = 0; } });
});
my_scripts.js
Возьми в руку карандашДопишите сценарий, чтобы он обрабатывал щелчки на других частях монстра (глаза,
нос и рот). Вскоре мы дополним обработчики дополнительной функциональностью.
Проследите, чтобы переменные и условные конструкции следовали в правильном по-
рядке для обнаружения девятого щелчка.
220 глава 5
решение упражнения
$(document).ready(function(){
$("#head").click(function(){ if (headclix < 9){ headclix += 1; } else{ headclix = 0; } });
});
my_scripts.js
var headclix = 0, eyeclix=0, noseclix= 0, mouthclix = 0;
$("#eyes").click(function() { if (eyeclix < 9){ eyeclix += 1; } else{ eyeclix = 0; }});
$("#nose").click(function() { if (noseclix < 9){ noseclix += 1; } else{ noseclix = 0; }});
$("#mouth").click(function() { if (mouthclix < 9){ mouthclix += 1; } else{ mouthclix = 0; }});
Обратите внимание: все функции click очень похожи друг на друга с минимальными от-клонениями. Нельзя ли повторно использовать один фрагмент кода?
Терпение — этим мы займемся в главе 7.
Теперь каждая часть лица монстра реагиру-ет на щелчки, а после девяти щелчков поло-са «перематывается» в начало.
В одной строке можно
объявить и инициа-
лизировать несколько
переменных, разделяя
их запятыми.
Вы обеспечили обработку щелчков на других частях монстра (глаза,
нос и рот), а также расположили переменные и условные конструкции
в правильном порядке для обнаружения девятого щелчка.
Возьми в руку карандаш Решение
дальше � 221
jquery эффекты и анимация
Пользовательский интерфейс
Модель анимации с молниями
Изображения должны проявляться и быстро исчезать, имитируя сверкание молнии.
Область головы
Область глаз
Область носа
Область рта
Рамка
Контейнерimg - lightning1img - lightning2img - lightning3
Щелкните, чтобы изменить голову монстра.
Щелкните, чтобы изменить глаза монстра.
Щелкните, чтобы изменить нос монстра.
Щелкните, чтобы изменить рот монстра.
Ýôôåêò ìîëíèè
Теперь займемся эффектом молнии. Прежде чем браться за реализацию эффекта, посмотрим, что об этом говорится в схеме приложения.
Изображения молнии вложены в контейнер div…
…молнии должны быстро проявляться и исчезать.
Возможно. Но нет ли чего-нибудь поинтереснее?В главе 1 мы воспользовались готовыми эффектами jQuery, а сейчас попробуем ра-зобраться поглубже.
Мы уже использовали эффекты изменения прозрачности в главе 1. Нельзя ли восполь-зоваться теми же средствами в приложении
«Собери монстра»?
222 глава 5
махинации со свойствами
Êàê jQuery âûïîëíÿåò àíèìàöèþ ýëåìåíòîâ?
Во время загрузки файла CSS браузер задает визуальные свойства элементов стра-ницы. При использовании встроенных эффектов jQuery интерпретатор Java изме-няет эти свойства CSS, и изменения происходят динамически прямо у вас перед глазами. Но никакого волшебства в этом нет... Все дело в свойствах CSS. Давайте еще раз вернемся к тому, что вы уже видели.
Эффекты jQuery изменяют свойства CSS «на ходу»,
в результате чего страница изменяется прямо перед
глазами пользователя.
Интерпретатор JS изменя-ет свойство CSS display выбранного элемента так, что тот становится види-мым.
show
Интерпретатор JS задает свой-ству CSS display выбранного элемента значение none; эле-мент перестает отображаться на странице.
hide
Если элемент скрыт, то ин-терпретатор JS отображает его, и наоборот.
toggle
Ìåòîäû hide, show è toggle èçìåíÿþò ñâîéñòâî CSS display
Методы hide, show и toggle работают со свойством display. Но нам нужно, чтобы части лица не просто появ-лялись, а «скользили», а молнии проявлялись и исчезали. Как вы думаете, какие свойства CSS изменяются jQuery в эффектах скольжения и проявления/исчезновения?
Мозговой
штурм
дальше � 223
jquery эффекты и анимация
Ýôôåêòû èçìåíåíèÿ ïðîçðà÷íîñòè èçìåíÿþò ñâîéñòâî CSS opacity
В эффекте проявления fadeIn интерпретатор JavaScript изменяет свойство CSS opacity выбран-ного элемента от 0 до 100.
fadeIn
В эффекте исчезновения fadeOut интерпретатор JavaScript изменяет свойство CSS opacity выбран-ного элемента от 100 до 0, но сохраняет на страни-це место, занимаемое элементом.
fadeOut
fadeTo выполняет анима-цию выбранного элемента до заданного уровня про-зрачности (в процентах).
fadeTo
Для любознательных
Свойство CSS opacity по-разному работает в раз-
ных браузерах. К счастью, jQuery берет на себя все
технические тонкости. Собственно, это единствен-
ное, что вам необходимо о них знать!
224 глава 5
добавь чуть-чуть скольжения
Ýôôåêò ñêîëüæåíèÿ
Интерпретатор JavaScript приказывает DOM уменьшить свойство CSS height выбранного элемента до 0, а затем задать свойству display значение none. По сути, эле-мент скрывается посредством скольжения.
Интерпретатор JavaScript снова делает выбранный эле-мент(-ы) видимым, для чего его свойство height увели-чивается от 0 до высоты, заданной в стиле CSS.
Интерпретатор JavaScript проверяет, имеет изображе-ние полную или нулевую высоту, и переключает эффект скольжения в зависимости от результата. Если высота элемента равна 0, то интерпретатор JavaScript использу-ет скольжение вниз, а при полной высоте используется скольжение вверх.
slideUp
slideDown
slideToggle
Модель DOM страницы
Это что, волшебство
какое-то?
Эй, DOM, уменьши высоту выбранно-го элемента до 0, а потом измени свойство display.
Интерпретатор JavaScript
дальше � 225
jquery эффекты и анимация
Какие из готовых эффектов jQuery подойдут для приложения «Собери мон-
стра»? Для каждого вида эффектов напишите, можно ли использовать их в
нашем случае, и объясните, почему вы выбрали (или не выбрали) данный
эффект.
Эффект Можно ли ис-
пользовать?
Почему?
Скрытие/ото-
бражение
элемента
Скольжение
Изменение
прозрачности
В jQuery включены готовые эффекты только для вертикального скольже-ния элементов.В jQuery не существует методов slideRight или slideLeft (по крайней мере на момент написания книги). Не беспокойтесь, вскоре мы решим эту проблему…
В jQuery не существует
методов slideRight и slideLeft.
Выходит, элементы могут скользить только вверх-вниз? А если мне нужно, чтобы они скользили горизонтально?
Возьми в руку карандаш
226 глава 5
решение упражнения
Какие из готовых эффектов jQuery подойдут для приложения
«Собери монстра»?
Эффект Можно ли ис-
пользовать
Почему?
Отображение/
скрытиеНет Эти эффекты в нашем приложении бесполезны, нам не нуж-
но анимировать свойство display каких-либо элементов.Скольжение Нет Чуть ближе, и все же не то. Полоса изображений должна
скользить влево. Методы SlideUp и slideDown изменяют свойство height, а нам нужно свойство left.
Изменение
прозрачностиДа Эффекты изменения прозрачности позволяют выполнить
пункт спецификации, в котором говорится, что изображе-ния молний должны быстро проявляться и исчезать, ими-тируя электрические разряды.
В спецификации говорится, что изображения молний должны быстро проявляться и исчезать, но для имитации сверкания изменения должны быть достаточно быстры-ми. Давайте поглубже разберемся в том, как работают эффекты изменения прозрачно-сти, и попробуем реализовать эффект сверкания молнии.
Êàê ðàáîòàþò ýôôåêòû èçìåíåíèÿ ïðîçðà÷íîñòè
$("#lightning1"). fadeIn("fast");
$("#lightning1").fadeIn(1000);
Идентификатор первого элемента img.
Параметр управляет скоро-стью завершения эффекта.
Используйте одно из строковых
значений: slow, normal или fast…
…или значение в миллисекундах. Например, если указать при вызове значение 1000, то анимация эффекта будет выполнена за одну секунду. 1 секунда = 1000 миллисекунд
Возьми в руку карандаш Решение
дальше � 227
jquery эффекты и анимация
Напишите пару строк кода jQuery, которые выполняют следующие операции:
Элемент #lightning1 проявляется с продолжительностью в 1/4 секунды.1
Присоедините к первому вызову еще один, обеспечивающий исчезновение элемента #lightning1 за 1/4 секунды.
2
Êîìáèíèðîâàííûå ýôôåêòû
Молнии должны проявляться и исчезать, и так несколько раз. Вместо того чтобы реализовывать повторяющиеся эффекты по отдельности, лучше воспользоваться сцепленными вызовами (кото-рые кратко упоминались в главе 4, когда мы занимались перемещениями по дереву DOM). jQuery поддерживает возможность сцепления вызовов для последовательного применения серии мето-дов к возвращаемому набору элементов. Как вы вскоре убедитесь, сцепление упро щает реализа-цию сверкания молний и делает запись более компактной.
$("#lightning1"). fadeIn().fadeOut();
Методы соединя-ются друг с другом, словно звенья цепи.
Элемент переходит из скрытого
состояния в состояние видимости
с нулевой прозрачностью…
…а затем растворяется до полной прозрачности. Если не указать продол-
жительность в круг лых скобках, по умолчанию ис-пользуется значение normal, что соответствует 400 мс, или 0.4 с.
Упражнение
228 глава 5
удар молнии
Çàäåðæêà ïðè èñïîëüçîâàíèè ýôôåêòîâ
function lightning_one(t){ $("#lightning1").fadeIn(250).fadeOut(250); setTimeout("lightning_one()",t);};
Эй, JavaScript, сделай мне новую функцию.
Имя, по которому будет вызываться функция.
В этой строке используют-ся эффекты jQuery.
Метод setTimeout при-казывает интерпрета-тору выполнить функ-цию и сделать паузу перед ее повторным выполнением.
Оцените силу JS: вы сообщаете интер претатору, что функция долж-на вызывать себя снова и снова.
Продолжительность задерж-ки (тайм-аут) задается в миллисекундах (как и про-должительность эффекта, о которой мы говорили не-сколько страниц назад).
Всего в трех строках кода мы создали функцию анимации молнии, срабатывающую по таймеру, для первого изображения молнии. Теперь напишите аналогичные функции для других изображений молнии.
Параметр, определяющий задержку между ударами молнии (переменная с именем t). Мы используем его в коде функции.
Вы знаете, как реализовать проявление и исчезновение молний, но в требованиях к проекту сказано, что разряды должны быть многократными. Во время грозы молнии не следуют непрерывно, между ними есть паузы. А значит, нужно организовать многократное применение эффекта.
Вспомните предыдущие главы: что мы использовали для повторяющихся операций? Правильно: функ-ции! Они появились в главе 3, когда мы создавали универсальную функцию click и генератор случайных чисел. В нашей ситуации можно использовать функции для выполнения эффекта, немного подождать и через некоторое время повторить вызов. Как же будет выглядеть функция для решения этой задачи?
Напишите пару строк кода jQuery, которые выполняют следующие операции:
Элемент #lightning1 проявляется с продолжительностью в 1/4 секунды.1
Присоедините к первому вызову еще один, обеспечивающий исчезновение элемента #lightning1 за 1/4 секунды.
2
$("#lightning1").fadeIn("250");
$("#lightning1").fadeIn("250").fadeOut("250");
дальше � 229
jquery эффекты и анимация
Расставьте магниты в правильном порядке. У вас должны получиться функции, повторяющие
эффект периодического сверкания молнии, для двух других изображений.
function
setTimeout(
};
$("#lightning2")
lightning_two
.fadeIn(250)
"lightning_two()",
t);
(t){
.fadeOut(250);
function
setTimeout(
};
$("#lightning3")
lightning_three
.fadeIn(250)
"lightning_three()",
t);
(t){
.fadeOut(250);
Развлечения с магнитами
230 глава 5
частоЗадаваемые
вопросы
решение упражнения
Расставьте магниты в правильном порядке. У вас должны получиться функции, повторя-
ющие эффект периодического сверкания молнии, для остальных изображений.
function
setTimeout(
};
$("#lightning2")
lightning_two
.fadeIn(250)
"lightning_two()", t);
(t){
.fadeOut(250);
function
setTimeout(
};
$("#lightning3")
lightning_three
.fadeIn(250)
"lightning_three()", t);
(t){
.fadeOut(250);
В: Разве fadeIn().fadeOut() не то же самое, что toggle?
О: Отличный вопрос! Нет, не то же. toggle — одиночный метод, который просто переключает выбранный элемент из скрытого состояния в видимое и наоборот, в зависи-мости от его текущего состояния. Цепочка из fadeIn и fadeOut создает эффект, при котором выбранный элемент(ы) сначала проявляется, а после завершения эффекта становится невидимым.
В: Новый метод setTimeout? Отку-да он взялся? Из jQuery или из JavaScript?
О: setTimeout — метод JavaScript, ко-торый может использоваться для управле-ния некоторыми аспектами анимаций jQuery. Мы поближе познакомимся с setTimeout в следующих главах, особенно в главе 7.
Если вы захотите узнать о setTimeout, посетите Mozilla Developer’s Center: https://developer.mozilla.org/en/window.setTimeout. Дополнительную информа-цию можно найти в превосходной книге
Дэвида Фленагана «JavaScript. Подробное руководство».
В: Когда я использую эффект hide, элемент просто исчезает. Как замедлить его исчезновение?
О: Чтобы «замедлить» действие hide, show или toggle, передайте значение продолжительности в круглых скобках. Пример использования hide из главы 1: $("#picframe").hide(500);
Развлечения с магнитами. Решение
дальше � 231
jquery эффекты и анимация
$(document).ready(function(){ var headclix = 0, eyeclix = 0, noseclix = 0, mouthclix = 0; lightning_one(4000); lightning_two(5000); lightning_three(7000);
$("#head").click(function(){ if (headclix < 9){headclix+=1;} else{headclix = 0;} });
$("#eyes").click(function(){ if (eyeclix < 9){eyeclix+=1;} else{eyeclix = 0;} });
$("#nose").click(function(){ if (noseclix < 9){noseclix+=1;} else{noseclix = 0;} });
$("#mouth").click(function(){ if (mouthclix < 9){mouthclix+=1;} else{mouthclix = 0;} });
});//end doc.onready function
function lightning_one(t){ $("#container #lightning1").fadeIn(250).fadeOut(250); setTimeout("lightning_one()",t); }; function lightning_two(t){ $("#container #lightning2").fadeIn("fast").fadeOut("fast"); setTimeout("lightning_two()",t); }; function lightning_three(t){ $("#container #lightning3").fadeIn("fast").fadeOut("fast"); setTimeout("lightning_three()",t); };
my_scripts.js
Числа в скобках — длительность задерж-ки (в миллисекундах), передаваемая методу setTimeout. Так мы управляем частотой вспышек.
Мы убрали часть разрывов строк для экономии места. Не беспокойтесь, если в вашем сце-нарии использует-ся другая разбивка строк.
Обновите файл сценариев приложения «Собери монстра» кодом из упражнения на предыдущей странице.
Âêëþ÷åíèå ôóíêöèé â ñöåíàðèéЗадание!
В этих строках вызывают-ся функции, выделенные жирным шрифтом в конце.
Определе-ния функций сверкания молний
232 глава 5
тест-драйв
Проект «Собери монстра»Развлекательное приложение «Собери монстра» адресовано детям целевой возрастной группы. Оно позволяет «собрать» изображение из 10 вариантов головы, глаз, носа и рта. Переключение частей монстра должно сопро-вождаться анимацией.вождаться анимацией.
Модель изменения лица монстраАнимация
Модель анимации с молниями
Откройте страницу в своем любимом браузере и посмотрите, как работает эффект сверкания молний. Эффект проявле-
ния/исчезновения объединен с мето-дом setTimeout.
Итак, к настоящему моменту у вас работают функции click, а три молнии сверкают с разными интервалами. Давайте вернемся к схе-ме и посмотрим, что еще осталось сделать.
Готовые эффекты удобны, но они не позволяют сде-лать все, что нам нужно.
Пора создать пользовательский эффект, который будет сдви-гать полосы частей лица мон-стра влево.
Последняя нерешенная задача этого проекта
Молнии проявля-ются и исчезают с разными интер-валами, чтобы сверкание выгляде-ло реалистичнее.
Пора сдвигать изображения влево, а ни один из готовых эффектов
не подходит. Нельзя ли восполь-зоваться каким-нибудь другим
методом?
Тест-драйв
дальше � 233
jquery эффекты и анимация
Ñàìîäåëüíûå ýôôåêòû è animate
В jQuery нет методов slideRight и slideLeft, а на этой стадии проекта без них не обойтись. Означает ли это, что проект «Собери монстра» зашел в тупик?
Вовсе нет, в jQuery существует метод animate для построения ваших собственных эффектов. С его помощью можно создавать пользовательские анимации, которые по своим возможностям далеко превосходят готовые, стандартные эффекты. Метод animate позволяет изменять свой-ства CSS выбранных элеметов, с возможностью одновременной анимации нескольких свойств.
Давайте посмотрим, что можно сделать с помощью метода animate.
Ýôôåêòû äâèæåíèÿ
Анимация позиционных свойств CSS создает ил-люзию движения графиче-ского элемента по экрану.
Какое свойство CSS потребуется для анимации сдвига частей лица монстра влево при каждом щелчке?
Ýôôåêòû ìàñøòàáèðîâàíèÿ
Анимация свойств CSS height и width создает иллюзию увеличения или уменьшения элемента.
Мозговой
штурм
234 глава 5
из области математики
×òî ìîæíî àíèìèðîâàòü?
Метод animate позволяет динамически изменять свойства шрифтов для создания текстовых эффектов. Также возможна одновременная анимация нескольких свойств CSS при одном вызове, что только до-бавляет интересных возможностей веб-приложениям.
При всей крутизне метода animate его возможности небезграничны. В его внутренней реализации ис-пользуются сложные математические вычисления (о которых вам, к счастью, беспокоиться не нужно), поэтому работать можно только со свойствами CSS, имеющими числовые значения. Знайте пределы воз-можностей, но не ограничивайте свое творческое воображение. Анимация обладает исключительной гибкостью, и с ней можно сделать много интересного.
Я уменьшаюсь, уменьшаюсь!Прощай, жестокий мир!
Я уменьшаюсь, уменьшаюсь!Прощай, жестокий мир!
Я уменьшаюсь, уменьшаюсь!Прощай, жестокий мир!
Я уменьшаюсь, уменьшаюсь!Прощай, жестокий мир!
Я уменьшаюсь, уменьшаюсь!Прощай, жестокий мир!
Òåêñòîâûå ýôôåêòû
Анимация шрифтовых свойств CSS способна создать иллюзию увеличения, уменьшения и полета текста.
Это всего лишь несколь-ко примеров. Для полного описания всех возможностей анимации нам понадобилось бы намного, намного больше места!
Метод animate работает только со свойствами CSS, имеющими числовые значения:
� borders, margin, padding
� element height, min-height и max-height
� element width, min-width и max-width
� font size
� bottom, left, right и top position
� background position
� letter spacing, word spacing
� text indent
� line height
Будьте осторожны!
дальше � 235
jquery эффекты и анимация
$("#my_div").animate({left:"100px"},500);
Выбираем элемент(-ы), к которому применяется анимация. Вызываем метод
animate.
Первый параметр animate определяет свойство CSS, к ко-торому применяется анимация.
Второй параметр опреде-ляет продолжительность анимации в миллисекун-дах. С его помощью можно управлять временем за-вершения анимации.
В этом примере анимация применяется к свойству CSS left…
…для которого за-дается значение "100px".
Первый аргумент передается всегда, без него анимация работать не будет. Второй параметр необязателен.
$("#my_div").animate({ opacity: 0, width: "200", height: "800" }, 5000);
Но одна из самых замечательных особенностей animate — возможность одновременного измене-ния нескольких свойств выбранных элементов.
В этом примере одновре-менно изменяются свойства прозрачности и размеров элемента.
На первый взгляд метод animate имеет много общего с другими методами, которые мы уже использовали.
Параметры свойств CSS должны задаваться по стандарту DOM, а не по стандарту CSS.
Как вы думаете, что при этом происходит в браузере? Как метод animate изменяет страницу прямо на гла-зах у пользователя?
Будьте осторожны!
напряги мозги
Метод animate под увеличительным стеклом
236 глава 5
в движении
Визуальные эффекты и анимация, которые вы видите на экране телевизора или кинотеатра, использу-ют иллюзию движения. Для достижения этой иллюзии мастера спецэффектов и художники-мультипли-каторы берут серию изображений и последовательно воспроизводят их с нужной частотой, вероятно, вы видели, как «оживают» рисунки в уголках тетрадей при быстром пролистывании страниц.
То же самое происходит и на экране браузера, правда, без серии готовых изображений. Вместо этого интерпретатор JavaScript многократно вызывает функцию, изменяющую стилевое оформление эле-мента. Браузер воспроизводит (перерисовывает) изменения на экране. В процессе изменения стилевого оформления создается иллюзия движения или изменения внешнего вида элемента.
Ìåòîä animate èçìåíÿåò ñòèëåâîå îôîðìëåíèå
Интерпретатор JavaScript устанавливает таймер на время выполнения анимации.
1
Интерпретатор JavaScript приказывает браузерному движку визуализации изменить свойство CSS, заданное в параметрах метода animate. Движок обе-спечивает визуальное отображение этих свойств CSS на экране.
2
Браузерный движок визуа-
лизации
Пока браузер отображает изменения в элементе, посетитель видит иллюзию движения.
4
Изменить свойство CSS left до 500px
за 400 миллисекунд.
Интерпретатор JavaScript
Интерпретатор многократно вызывает функцию, изменяю щую свойство CSS элемента (до завершения работы таймера). При каждом выполнении функции изменения воспроизводятся на экране.
3
Если параметр duration
при вызове animate не задан,
по умолчанию используется
значение 400 миллисекунд.
Браузер
Интерпретатор JavaScript
Думаю, это можно будет устроить через несколько миллисе-
кунд.
Я хочу запланиро-вать перерисовку
экрана.
дальше � 237
jquery эффекты и анимация
Анимация одновременного из-менения левого и правого полей всех абзацев.
Анимация изменения правой сто-роны #my_div до 0 за половину секунды.
Анимация межбуквенных интерва-лов всех абзацев с продолжитель-ностью по умолчанию (400 милли-секунд).
Анимация одновременного изме-нения внутренних полей и шири-ны #my_div.
Анимация изменения положения верхней стороны #my_div с про-должительностью slow.
Анимация изменения высоты всех изображений с продолжительно-стью fast.
Анимация изменения ширины #my_div, продолжающегося 1/4 секунды.
$("#my_div").animate({top: "150px"}, "slow")
$("p").animate({ marginLeft:"150px", marginRight:"150px"});
$("#my_div").animate({width: "30%"}, 250)
$("#my_div").animate({right: "0"}, 500)
$("p").animate({letterSpacing:"15px"});
$("#my_div").animate({ padding: "200px", width: "30%"}, "slow")
$("img").animate({height: "20px"}, "fast")
Соедините каждый фрагмент кода пользовательской анимации с его описанием.
Кто и что делает?аеааеееееееееееееееее
238 глава 5
решение упражнения
Соедините каждый фрагмент кода пользовательской анимации с его описанием.
$("#my_div").animate({top: "150px"}, "slow")
$("p").animate({ marginLeft:"150px", marginRight:"150px"});
$("#my_div").animate({width: "30%"}, 250)
$("#my_div").animate({right: "0"}, 500)
$("p").animate({letterSpacing:"15px"});
$("#my_div").animate({ padding: "200px", width: "30%"}, "slow")
$("img").animate({height: "20px"}, "fast")
Анимация одновременного изме-нения левого и правого полей всех абзацев.
Анимация изменения правой сто-роны #my_div до 0 за половину секунды.
Анимация межбуквенных интерва-лов всех абзацев с продолжитель-ностью по умолчанию (400 милли-секунд).
Анимация одновременного изме-нения внутренних полей и шири-ны #my_div.
Анимация изменения положения верхней стороны #my_div с про-должительностью slow.
Анимация изменения высоты всех изображений с продолжительно-стью fast.
Анимация изменения ширины #my_div, продолжающегося 1/4 секунды.
Кто и что делает?аеааеееееееееееееееее
Решение
дальше � 239
jquery эффекты и анимация
Òåêóùåå çíà÷åíèå ñâîéñòâà Çàäàííîå çíà÷åíèå ñâîéñòâà
Следует помнить, что метод animate изменяет текущее значение свойства CSS до значе-ния, заданного первым параметром. Чтобы пользовательская анимация была эффектив-ной, необходимо тщательно учесть, какое значение хранится в CSS в данный момент. В предыдущем примере значение left элемента #my_div изменялось до 100px. То, что при этом произойдет на экране, полностью зависит от текущего значения свойства left элемента #my_div.
#my_div{ left: 20px;}
$("#my_div").animate({left:"100px"});
#my_div
#my_div пере-мещается на 80 пикселов вправо.
Òåêóùåå çíà÷åíèå ñâîéñòâà Çàäàííîå çíà÷åíèå ñâîéñòâà
#my_div{ left: 200px;}
$("#my_div").animate({left:"100px"});
#my_div находится в началь-ной позиции 200px.
#my_div пере-мещается на 100 пикселов влево.
Если свойство имеет другое текущее значение, то и результат будет другим.
Все относительно.Чтобы части лица монстра скользили именно так, как нам нужно, нужно продумать их текущие позиции и то, как они должны изменяться относи-тельно их положения на момент последнего изменения.
Îòêóäà è êóäà?
В анимации используется абсолютная позиция.
Прекрасно, но как это нам поможет с приложением «Собери монстра»?
240 глава 5
относительно просто
Îòíîñèòåëüíàÿ àíèìàöèÿ = êàæäûé ðàç ïåðåìåñòèòü íà ñòîëüêî
При абсолютной анимации элемент перемещается в абсолютную позицию в визуальной си-стеме координат. При относительной анимации перемещение элемента задается относи-тельно последней позиции, в которую он переместился в процессе анимации.
Вспомните, что полосы изображений, которые должны отображаться, вложены в элемент div с идентификатором #pic_box. Свойству left элемента div#pic_box в текущем коде CSS задается значение 91px. Давайте подумаем, как должны двигаться полосы изображений для реализации эффекта горизонтального скольжения.
Àáñîëþòíûå è îòíîñèòåëüíûå ïåðåìåùåíèÿ ýëåìåíòîâ
367 пикселов367 пикселов 367 пикселовСначала отображается первый фрагмент головы (относительная пози-ция 0 пикселов).
Каждый раз, когда пользователь щелкает, поло-са изображений должна смещаться на 367 пикселов влево.
Итак, метод animate должен смещать изображение на -367 пикселов при каж-дом вызове функции.
Вернемся к примеру абсолютного позиционирования на предыдущей странице:
$("#my_div").animate({ left:"100px"}); $("#head").animate({left:"???"});
Команда задает свойству left
элемента #my_div абсолютное
значение 100 пикселов.Но как приказать animate сме-
щать элемент на -367 пикселов
при каждом вызове?
Но как обозначить относительное перемещение элемента при вызове метода animate?
дальше � 241
jquery эффекты и анимация
$("#box").animate({left:"+=20"});
a = 20 a += 30
w Напишите пару строк кода jQuery, которые выполняют следующие операции:
В JavaScript существуют специальные операторы, которые сдвигают элемент(ы) на одинаковую величину при каждом вызове animate — операторы присваивания. Они обычно используются для присваивания, при котором новое значение переменной получается увеличением старого значе-ния на некоторую величину. Впрочем, звучит все это намного сложнее, чем на самом деле.
Êîìáèíèðîâàííûå îïåðàòîðû
Знак равенства — оператор
присваивания.
При объединении арифметических операторов со знаком = получается удобная сокращенная запись.
Оператор = присваивает переменной a значение 20.
Плюс в сочетании со знаком = является
сокращенной записью a = a + 30.
a -= 10Минус в сочетании со знаком = означает a = a – 10.
Элемент с идентификатором box смещается
на 20 пикселов при каждом вызове метода animate.
Комбинированные операторы помогают создавать относительную анимацию: новое значение вычисляется по формуле «текущее значение плюс или минус смещение в пикселах».
Вот что происходит с #box при каждом вызове метода animate:
Другие комбиниро-ванные операторы
присваивания:
� a *= 5 — это сокращенная запись операции a = a * 5.
� a /= 2 — это сокращенная запись операции a = a/2.
left = 20left = 0 left = 40
Изначально left равно 0.
Многократное изменение свойства left приводит к смещению элемента вправо в окне браузера.
Метод animate: left += 20.
Метод animate: left += 20.
Элемент #head перемещается на 367 пикселов влево при каждом вызове animate. Перемещение выполняется за 0,5 секунды.
1
Элемент #head перемещается обратно в исходную позицию (left:0px). Перемещение выполняется за 0,5 секунды.
2
Упражнение
242 глава 5
решение упраженения
В: Некоторые пользователи считают, что анимация мешает нормальному вос-приятию веб-страницы. Что делать, если я захочу разрешить пользователю от-ключать анимацию?
О: Справедливое замечание, некоторые пользователи считают, что анимация раз-дражает и усложняет работу с программой. Если вы хотите, чтобы пользователи могли отключить анимацию, свяжите функцию click кнопки (вы уже знаете, как это делается) со следующей строкой кода:
$.fx.off = true;Также для остановки анимации в jQuery может использоваться метод stop. Обе возможности описаны на сайте jQuery:
http://api.jquery.com/jQuery.fx.off/http://api.jquery.com/stop/
В: Вы пишете: «Параметры свойств CSS должны задаваться по стандарту DOM, а не по стандарту CSS». Что бы это значило?
О: Отличный вопрос! Метод animate получает параметры по стандарту DOM («синтаксис DOM»), а не по стандарту CSS.Различия лучше пояснить на конкретном примере. Чтобы задать толщину границы div в синтаксисе CSS, можно использовать следующую запись:
div { border-style:solid; border-width:5px; }
Предположим, что вы хотите анимировать изменение толщины границы. В jQuery для этого свойство задается в синтаксисе DOM:
$("div").animate({borderWidth:30},"slow");
Обратите внимание: в синтаксисе CSS имя свойства записывается в виде border-width, тогда как в синтаксисе DOM ис-пользуется запись borderWidth.
Различия между двумя вариантами записи более подробно рассматриваются в следу-ющей статье:
http://www.oxfordu.net/webdesign/dom/straight_text.html
В: А если я захочу анимировать из-менение цвета?
О: Для выполнения анимации цветовых переходов необходимо использовать би-блиотеку jQuery UI, которая поддерживает больше эффектов, чем jQuery. Мы будем рассматривать jQuery UI в главе 10, но без рассмотрения эффектов. Когда вы научи-тесь загружать и включать jQuery UI в ваше веб-приложение, с анимацией цветов осо-бых проблем уже не будет.
Напишите пару строк кода jQuery, которые выполняют следующие операции:
Элемент #head перемещается на 367 пикселов влево при каждом вызове animate. Перемещение выполняется за 0,5 секунды.
1
Элемент #head перемещается обратно в исходную позицию (left:0px). Перемещение выполняется за 0,5 секунды.
2
$("#head").animate({left:"-=367px"},500);
$("#head").animate({left:"0px"},500); Абсолютная анимация переводит голову монстра в исходное состояние, ими-тируя «перемотку».
частоЗадаваемые
вопросы
дальше � 243
jquery эффекты и анимация
Измените файл сценариев приложения «Собери монстра» — включите в него код, созданный нами в упражнении на предыдущей странице.
Âêëþ÷åíèå âûçîâîâ animate â ñöåíàðíûé êîä
$("#head").click(function(){ if (headclix < 9){ $(this).animate({left:"-=367px"},500); headclix+=1; } else{ $(this).animate({left:"0px"},500); headclix = 0; } }); $("#eyes").click(function(){ if (eyeclix < 9){ $(this).animate({left:"-=367px"},500); eyeclix+=1; } else{ $(this).animate({left:"0px"},500); eyeclix = 0; } }); $("#nose").click(function(){ if (noseclix < 9){ $(this).animate({left:"-=367px"},500); noseclix+=1; } else{ $(this).animate({left:"0px"},500); noseclix = 0; } }); $("#mouth").click(function(){ if (mouthclix < 9){ $(this).animate({left:"-=367px"},500); mouthclix+=1; } else{ $(this).animate({left:"0px"},500); mouthclix = 0; }
Задание!
Здесь можно использовать ключевое слово this, так как мы находимся внутри функции элемента, на котором был сделан щелчок.
my_scripts.js
244 глава 5
тест-драйв
Откройте страницу в своем любимом браузере и убедитесь в том, что все работает правильно.
Мы реализовали пользова-тельский эффект горизон-тального скольжения.
Несколько щелчков мышью... и пользователь может создать собственное лицо монстра.
Тест-драйв
дальше � 245
jquery эффекты и анимация
Руководитель веб-проектов доволен результатами работы. Мы использовали гото-вые эффекты jQuery в сочетании с пользовательскими эффектами, созданными специально для конкретного приложения.
Ñìîòðè, ìàìà! Ðàáîòàåò áåç Flash!
Потрясающе! Пойду напугаю младшую
сестру монстром, кото-рого я сделала!
Целевой аудитории от 6 до 10 лет приложение понравилось. Все работает без Flash и дополнительных модулей браузера... jQuery нам безусловно при-
годится!
Вот здорово! Я создал столько монстров,
что сбился со счета!
246 глава 5
ваш инструментарий jquery
Âàø èíñòðóìåíòàðèé jQuery
Глава 5 осталась позади, а ваш творческий инструмен-тарий расширился: добавились эффекты изменения прозрачности и скольжения, а также пользовательская анимация.
Эффекты изменения про-
зрачности
Изменение уровня прозрачности
элементов:
fadeIn
fadeOut
fadeTo
Эффекты скольженияИзменение высоты элементов:slideUp
slideDownslideToggle
animate
Метод позволяет создавать пользовательские анима-
ции, когда готовых эффектов jQuery недостаточно.
Выполняет анимацию свойств CSS во времени.
Работает только со свойствами CSS, имеющими
числовые значения.
Перемещение элементов бывает абсолютным или
относительным.
Комбинированные операторы присваивания
(+=, -=) упрощают относительную анимацию.
ГЛА
ВА 5
jQuery и JavaScript6
Люк jQuery, я твой отец!
Силы jQuery небезграничны. Хотя эта библиотека написана на JavaScript, к сожалению, она позволяет сделать не все, на что способен язык-родитель. В этой главе мы рассмотрим некоторые возможности JavaScript, необходимые для создания современных сайтов, и их применение в jQuery для создания пользовательских списков и объектов, а также средства перебора списков и объектов, которые существенно упростят вашу работу.
Сынок, есть некоторые вещи, с которыми ты один
просто не справишься...
248 глава 6
jquery для картежников
От: Head First LoungeТема: Блэкджек на сайте
Привет!
Это твои знакомые из клуба «Head First». Надеемся, ты поможешь нам раз-
работать новое приложение для нашего сайта.
Нам бы ОЧЕНЬ хотелось иметь приложение для игры в блэкджек.
Справишься?
В идеале игрок щелкает на странице и получает две карты, с возможностью
потребовать сдачи дополнительных карт.
Правила нашего клуба, которые нам хотелось бы использовать:
1. Туз ВСЕГДА дает 11 очков (а не 1).
2. Если сумма очков игрока превышает 21 — перебор, игрок проиграл, игра
закончена.
3. Если сумма очков на руках игрока 21 — блэкджек, игра закончена.
4. Если сумма очков игрока не превышает 21, а на руках у него пять карт,
то игра закончена, а игрок побеждает.
Если ни одно из этих условий не выполнено, игрок может взять следующую
карту (или остановить сдачу).
Если оно из правил/условий выполнено, игра закончена.
Игрок должен иметь возможность сбросить текущую игру и начать заново.
Мы не хотим, чтобы игроку приходилось перезагружать страницу вручную.
Игра должна все делать сама.
Можешь сделать это для нас? Мы будем вечно благодарны!
-- КлубHead First
Ïðîãðàììèðóåì áëýêäæåê
Слухи о вашем мастерстве jQuery распространяются молниеносно. Смотрите, вам пришло сообщение из клуба «Head First», в котором вас просят помочь с разработкой очередного развлекательного приложения.
дальше � 249
jquery и javascript
Джим
Фрэнк
ДжоДжим: Парни, вы прочитали сообщение из клуба «Head First»?
Фрэнк: Да, они хотят разместить на своем сайте упрощенную ре-ализацию блэкджека. Мне кажется, это тривиально.
Джим: Элементарно? Но ведь это блэкджек! Нам понадобится колода карт, дилер, счетчик суммы очков... и так далее. И ты ду-маешь, что мы с этим справимся?
Джо: Просто не будет, но я думаю, что мы справимся. Как ты и сказал, кто-то должен сдавать карты. Мы напишем для этого функцию. Вероятно, в этой функции можно будет использовать наш старый генератор случайных чисел.
Джим: Кстати, да. А что с картами? Ведь их в колоде 52.
Фрэнк: Мы можем просто составить большой список и каждый раз выбирать случайную карту из списка.
Джим: Но как избежать повторного выбора одной карты?
Фрэнк: Пожалуй, я знаю, как это сделать...
Джим: Ого, впечатляет! А как насчет запоминания того, какие карты уже вышли? И подсчета очков?
Фрэнк: Ты меня подловил. Я пока не знаю, как это сделать.
Джо: Спокойно! В JavaScript и jQuery найдется немало полезных возможностей, которые нам помогут.
Джим: А зачем JavaScript? Мы можем использовать переменные или массивы jQuery для информации о картах. Я думал, нам не придется лезть в дебри JavaScript, раз уж мы используем jQuery…
Фрэнк: Переменные не решат проблем, в них в любой момент времени может храниться только конкретное значение: строка, текст или отдельный элемент страницы. А массивы jQuery по-зволяют хранить несколько значений, но это могут быть только элементы DOM, возвращаемые селектором.
Джо: Да, ты прав. Нам потребуется что-то более гибкое.
Фрэнк: Скажем, возможность определения наших собственных структур и типов переменных.
Джо: Снова в точку! А для создания структур нам понадобится JavaScript…
250 глава 6
объективный взгляд
Îáúåêòû è õðàíåíèå äàííûõ
До настоящего момента мы использовали для хранения данных переменные и массивы. Переменные обеспечивают самый простой вариант хранения: одно значение связывается с одним именем. Хране-ние данных в массивах более эффективно: несколько значений связываются с одним именем.
Ïåðåìåííàÿ Ìàññèâ
Îáúåêò
Данные объекта хра-нятся в свойствах.
Имя свойствасвязывается… …со значением.Данные, описывающие
самолет, объединяются в одну логическую группу.
В переменной хранится одно значение. В массиве хранится несколько значений.
var a = 42; var v = [2, 3, 4]
leopardObject={ num_spots:"23", color:"brown"};
planeObject={ engines:"4", type:"passenger", propellor: "No"};
Объекты — еще более гибкая схема хранения данных. Они используются, когда для описания некото-рой сущности необходимо сохранить несколько переменных. Внутри объекта переменные называются свойствами. Объект может содержать функции, предназначенные для взаимодействия со свойствами объекта. Такая функция, созданная внутри объекта, называется методом.
Какими свойствами может обладать объект карты?
Объекты использу-
ются для хранения
нескольких значений,
описывающих некото-
рую сущность.
planeObject.engines;leopardObject.color;
Для обращения к свойствам объекта используется «точечная запись»:
Объект Его свойствоМозговой
штурм
дальше � 251
jquery и javascript
Ïîñòðîåíèå ñîáñòâåííûõ îáúåêòîâ
Объекты позволяют создавать ваши собственные переменные, которые работают именно так, как нуж-но вам. Вы можете создать объект, предназначенный для однократного использования, или же создать «шаблон» для построения объектов, который может использоваться снова и снова. О повторном ис-пользовании объектов мы поговорим чуть позже, а пока обсудим создание «одноразовых» объектов, а также рассмотрим некоторые термины и схемы, связанные с объектом.
Существует стандартный способ описания объектов с использованием диаграмм UML (Unified Modeling Language). UML — международный стандарт описания объектов в объектно-ориентирован-ном программировании.
Переменная, связанная с объектом, называется свойством объекта. Функция, связанная с объектом, на-зывается методом объекта. Объекты, рассчитанные на одноразовое использование, создаются ключе-вым словом var, как и все остальные переменные, встречавшиеся нам до настоящего момента.
Оказывается, практически все данные в jQuery и JavaScript —объекты.
Это относится к элементам, массивам, функциям, числам и дажестрокам, — все они имеют методы и свойства.
Имя объекта
Свойства объекта
Методы объекта
var myCountry = {
getCapital : function() {
alert(this.myCapital);
},
myName : 'USA',
myCapital : 'Washington DC'
},
Создаем объект с именем myCountry.
Создаем метод объ-екта с именем getCapital.
Создаем свойства объекта с име-нами myName и myCapital.
Задаем значения свойств.
Определение объекта всегда заключает-ся в фигурные скобки.
Эта функция выполняется при вызове метода.
UML-äèàãðàììà îáúåêòà
myCountry
myNamemyCapital
getCapital()
Эта структура покажет, как устроен ваш объект. Прежде чем браться за написание кода, полезно свериться с диаграммами UML.
А вот как этот объект определяется в программном коде:
Р А СС Л А Б Ь Т Е С Ь
252 глава 6
объекты по шаблону
Ñîçäàíèå îáúåêòîâ äëÿ ïîâòîðíîãî èñïîëüçîâàíèÿ
У объектов есть одна интересная особенность: они могут иметь одинаковую структу-ру, но содержать разные значения свойств (или переменных). Как и в случае с функ-циями, рассчитанными на многократное использование (как мы делали в главе 3), можно создать «шаблон» (или конструктор) объекта, чтобы использовать его по-вторно. Конструктор объекта также может использоваться для создания экземпляров объекта.
Конструктор — всего лишь функция, поэтому для создания конструктора объекта следует использовать ключевое слово function вместо ключевого слова var. Далее ключевое слово new используется для создания нового экземпляра объекта.
function myPerson(a,b){
this.name = a;
this.age = b;
}
Имя объекта
Свойства объекта
Параметры/аргументы функции
Задаем значения свойств объекта.
Как вы думаете, где можно использовать такие объекты?
Хмм, словно план дома: один раз рисую, затем использую снова и снова. Это сэкономит
мне немало времени!
Объект в виде диаграммы UML
myPerson
nameage
Мозговой
штурм
дальше � 253
jquery и javascript
myCountry.getCapital();
alert(myCountry.myName);
Âçàèìîäåéñòâèå ñ îáúåêòàìè
После создания экземпляра объекта (независимо от того, создали ли его вы или кто-то другой) все операции с ним выполняются при помощи оператора «точка» (.). Чтобы вы лучше поняли, как работает этот механизм, давайте по-внимательнее присмотримся к только что определенным объектам myCountry и myPerson.
var actor1 = new myPerson('Jack', '42');
var actor2 = new myPerson('Mary', '33');
alert(actor1.name);
alert(actor2.age);
Значения, пере-данные в аргумен-тах функции new, задают значения свойств.
Обращение к свойству name экземпляра объекта myPerson с именем actor1
На странице выво-дится текст «Jack».
Обращение к свойству age property экземпляра объекта
myPerson с именем actor2 (в дан-
ном случае значение равно 33)
Создание новых экземпляров объ-екта myPerson с именами actor1 и actor2
Обращение к свойству myNameНа странице выво-дится текст «USA».
Вызов метода getCapitalНа странице будет выведен текст «Washington DC».
Новый экземпляр объекта создается командой «new ».
Да! Отличная мысль.Давайте подготовим страницу HTML и посмо-трим, как создать объект, представляющий карту.
Кажется, я начинаю понимать... Я могу создать объект для представления карт
в колоде?
Оператор «точка» ис-пользуется по схеме имя_объекта.имя_ме-тода() или имя_объекта.имя_свойства().
254 глава 6
игра начинается
Ïîäãîòîâêà ñòðàíèöû
Ну что, скоро я буду сдавать
карты?
Задание!
Создайте файлы HMTL и CSS по приведенной ниже инфор-мации. Не забудьте создать файл my_scripts.js в папке scripts. На следующих страницах мы включим в него достаточно большой объем кода. Графику для всей главы можно загру-зить по адресу: http://thinkjquery.com/chapter06/images.zip.
<!DOCTYPE html>
<html>
<head>
<title>Head First Black Jack</title>
<link href="styles/my_style.css" rel="stylesheet">
</head>
<body>
<div id="main">
<h1>Click to reveal your cards</h1>
<h3 id="hdrTotal"></h3><h3 id="hdrResult"></h3>
<div id="my_hand">
</div>
<div id="controls">
<div id="btnDeal">
<img src="images/deck_small.jpg">
</div>
</div>
</div>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script src="scripts/my_scripts.js"></script>
</body>
</html>
index.html
>
#controls{
clear:both;
}
#my_hand{
clear:both;
border: 1px solid gray;
height: 250px;
width: 835px;
}
h3 {
display: inline;
padding-right: 40px;
}.current_hand{
float:left;
}
my_style.css
дальше � 255
jquery и javascript
Используя приведенную ниже UML-диаграмму объекта card, определите объект card с тремя параметрами name, suit и value. Значения параметров должны присваиваться соответствующим свойствам объекта. Этот конкретный объект пока не содержит ни одного метода. Часть кода мы уже написали за вас.
function card( ) {
}
Откройте страницу index.html в своем любимом бра-узере, ознакомьтесь с об-щей структурой страницы.
card
namesuitvalue
Тест-драйв
Упражнение
256 глава 6
решение упражнения
Ниже приведено определение объекта card. Включите его в файл my_scripts.js (раздел $(document).ready(function(){ });). Пока это весь код, который содержится в файле.
В: Чем «одноразовые» объекты отли-чаются от «многоразовых», пригодных для повторного использования?
О: «Одноразовый» объект — всего лишь особая форма объявления переменной, пригодной для хранения нескольких блоков информации. «Многоразовые» объекты представляют собой шаблоны, по которым можно создать сколько угодно экземпляров нужного объекта, причем каждый экземпляр содержит свой набор информации, описы-вающей объект.
В: Кажется, вы используете разные спо-собы задания свойств. Это так?
О: Да, так. Значения свойств могут за-даваться как с использованием оператора присваивания (=), так и с использованием
двоеточия (:), как мы сделали в примере. Оба способа являются действительными и взаимозаменяемыми.
В: Что еще мне нужно знать об объ-ектах?
О: Объекты JavaScript — достаточно сложная тема. Позднее в этой книге мы бу-дем использовать запись JSON ( JavaScript Object Notation). В этой записи обращение к свойствам производится несколько иным способом, который также может применять-ся к объектам JavaScript (так называемое «обращение по ключу»). Вместо записи:
object.my_propertyиспользуется запись:
object['my_property']
Результат остается неизменным — обра-щение к значению свойства
my_property.
В: Откуда появился стандарт UML?
О: Стандарт UML родился в середине 90-х, когда компании пытались разработать наглядный способ описания объектов. С тех пор UML прошел несколько циклов развития, а несколько конкурирующих частных фирм пытались утвердить свою версию в каче-стве общепринятого стандарта. К счастью, единый стандарт существует, и каждый разработчик со знанием UML сможет чи-тать и понимать диаграммы и информацию из других источников UML.
function card( name, suit, value ) {
this.name = name;
this.suit = suit;
this.value = value;
}
card
namesuitvalue
my_scripts.js
Ключевое слово function позволяет
многократно использовать определение.
Значения аргументов присваиваются свой-ствам объекта.
частоЗадаваемые
вопросы
дальше � 257
jquery и javascript
È ñíîâà ìàññèâû
Несколько элементов данных можно объединить в массив. Ячейки массива не-обязательно имеют отношение друг к другу, но такой способ хранения данных упрощает работу с ними. В главе 4 мы уже видели, как селектор jQuery возвраща-ет данные и сохраняет их в массиве. Сейчас мы воспользуемся JavaScript, чтобы работа с массивами стала еще эффективнее.
Ячейки массива могут содержать данные любого типа: строки, числа, объекты, даже элементы HTML! Существует несколько способов создания массивов:
И как упоминалось ранее, массивы тоже являются объектами, а значит, обладают методами и свойствами. Популярное свой-ство объекта length возвращает коли-чество ячеек в массиве. Для обращения к свойству length используется запись вида имя_массива.length.
var my_arr1 = new Array();
var my_arr2 = new Array('USA', 'China', 'Japan', 'Ireland');
var my_arr3 = ['USA', 'China', 'Japan', 'Ireland'];
Создание массива без ключевого слова new, но с заданием значений ячеек (перечисляемых в квадратных скобках [ ])
Создание массива ключевым словом new с заданием зна-чений ячеекСоздание пустого массива ключевым словом new
Не существует различий между способами созда-ния массивов.
На практике они выбира-ются впере мешку в зави-симости от назна че ния массива. Чтобы найти спи-
сок мето дов объекта массива, используйте в по-исковой системе строку «JavaScript array methods».
Это снова я! Мы уже встречались
в главе 4.
Получается, объект card будет очень полезным, но нам придется как-то отслеживать отыгранные
карты, верно?
Верно.Нам понадобится механизм хра-нения сданных карт и обращения к ним при сдаче. К счастью, мы уже знаем, как это делается…
Будьте осторожны!
258 глава 6
ячейки и индексы
Îáðàùåíèå ê ÿ÷åéêàì ìàññèâà
В отличие от создания массивов, существует только один способ обращения к информации, хра-нящейся в ячейках. Индексирование массивов начинается с 0 — первой ячейке массива соответ-ствует порядковый номер (или индекс) 0. Мы уже использовали индексы в главе 3; если вы забыли, что это такое, вернитесь к ней и освежите память.
alert( my_arr2[0] ) ;
// В окне сообщения выводится строка USA
alert( my_arr3[2] );
// В окне сообщения выводится строка Japan
alert( my_arr1[1] );
// Ошибка, пустая ячейка
При обращении к ячейке массива по индексу кавычки не нужны.
При обращении к ячейкам массива всегда используются квадратные скобки [ ].
Имя массива, соз-данного на с. 257
При попытке обращения по несуществующему ин-дексу происходит ошибка.
Индекс ячейки определяет
ее позицию в массиве.Хорошо, у нас есть массив с запол-
ненными ячейками. И дальше нам так и придется работать с исходными
данными?
Конечно, нет!С ячейками легко выполняются операции добавления, изменения и удаления. Давайте посмотрим, как это делается.
Первой ячейке массива соот-ветствует индекс 0, второй — индекс 1 и т. д.
дальше � 259
jquery и javascript
Äîáàâëåíèå è îáíîâëåíèå ÿ÷ååê
В массив можно включить сколько угодно элементов. В приведенных ранее примерах в массивы my_arr2 и my_arr3 были изначально сохранены данные, а массив my_arr1 остался пустым. Однако в массиве можно добавлять новые и изменять существующие ячейки, причем эти операции также осуществляются по индексу. Рассмотрим несколько разных способов обновления массивов:
my_arr1[0] = "France";
alert( my_arr1[0] );
// Выводится строка France
my_arr1[1] = "Spain" ;
my_arr1[0] = "Italy" ;
alert( my_arr1[0] );
// Выводится строка Italy
my_arr3[2] = "Canada";
alert( my_arr3[2] );
// Выводится строка Canada
Задаем значение первой ячейки массива my_arr1.
Обновляем значение первой ячейки массива my_arr1.
Добавляем вторую ячейку в массив my_arr1.
Обновляем значение третьей ячейки массива my_arr3.
В файле my_scripts.js, после кода определения объекта card, создайте массив с именем deck, содержащий все 52 карты стандартной колоды.Вы можете использовать уже созданный объект card и многократно вы-зывать конструктор с нужными параметрами для создания каждой карты — от туза до короля с разными мастями (трефы, черви, бубны, пики) и ценно-стью (туз — 11 очков, двойка — 2 очка и т. д.).
Упражнение
260 глава 6
решение упражнения
Не забудьте, что список значений должен быть заключен в квадратные скобки.
Но в массиве так много карт! Похоже, для их
извлечения нам придется снова написать здоровенный блок кода. Тоже мне развлечение!
Файл my_scripts.js содержит массив deck c 52 картами стандартной колоды, а также определение объекта card. Для создания каждой карты используйте объект card и вызывайте конструктор с нужными параметрами.
Необязательно.
Конечно, к ячейкам можно обращаться по индексу, но мы также можем после-довательно пере-брать все ячейки при помощи конструк-ции, напоминающей each (см. главу 3), и нам не придется писать длинный код для каждой карты.
Пора познакомиться с циклами…
var deck = [
new card('Ace', 'Hearts',11),
new card('Two', 'Hearts',2),
new card('Three', 'Hearts',3),
new card('Four', 'Hearts',4),
new card('King', 'Hearts',10),
new card('Ace', 'Diamonds',11),
new card('Two', 'Diamonds',2),
new card('Three', 'Diamonds',3),
new card('Queen', 'Diamonds',10),
new card('King', 'Diamonds',10),
new card('Ace', 'Clubs',11),
new card('Two', 'Clubs',2),
new card('King', 'Clubs',10),
new card('Ace', 'Spades',11),
new card('Two', 'Spades',2),
new card('Three', 'Spades',3),
Не заббудьте чт
new card('Jack', 'Spades',10),
new card('Queen', 'Spades',10),
new card('King', 'Spades',10)
];
my_scripts.js
При создании каждого объекта card передаются три параметра.Задаем имя массива.
дальше � 261
jquery и javascript
Ïîâòîðåíèå îïåðàöèé
В нашем приложении придется часто сдавать и возвращать карты в массив. К счастью, в JavaScript как раз для подобных ситуаций существуют циклы. Самое интересное, что вы ими уже пользовались: в гла-ве 3 метод jQuery each использовался для перебора элементов на основании селектора jQuery. На этот раз у нас больше свободы выбора, так как в JavaScript существует несколько разновидностей циклов, которые имеют слегка различающийся синтаксис и предназначены для разных целей.
Да, мне нравится повторять одно и то же
много раз!
Циклы for выполняют фрагмент кода
заранее определенное количество раз.
Циклы do...while выполняют фрагмент
кода и повторяют его, пока не будет
выполнено некоторое условие.
ИнициализацияВыполняется один раз в начале цикла.
1
Проверка условияПринятие решения об остановке цикла или выполнении сле-дующей итерации (обычно в зависимости от значения пере-менной).
2
Тело циклаОсновной код, повторяемый при каждом выполнении цикла.
3
ОбновлениеОбновление переменных, используемых при проверке условия.
4
Цикл for:
1 2 3 4 2 3 4... ... ... ... ... ... ...
Цикл do...while:
1 3 4 2 3 4 2... ... ... ... ... ... ...
Одно выпол-нение цикла
Другое выполне-ние цикла
Одно выпол-нение цикла
Другое выполне-ние цикла
Циклы for идеально подходят, когда код выпол-няется заранее известное количество раз. Это чис-ло должно быть известно до начала цикла, иначе выполнение может затянуться до бесконечности. Цикл for может не выполняться или много раз вы-полняться в зависимости от значений переменных.
Цикл do...while выполняет код минимум один раз, а потом продолжает выполнять его до тех пор, пока не будет выполнено некоторое условие (ска-жем, логическая переменная сменит состояние или счетчик в коде достигнет заданного значения). Цикл do...while выполняется один и более раз.
Все циклы независимо от их типа состоят из четырех частей.
262 глава 6
подробнее о циклах
Öèêëû for
for( var i=0 ; i < my_arr2.length ; i++ ){
alert( my_arr2[i] );
}
.length — общий метод всех массивов, возвращает количество заполненных ячеек в цикле.
Переменная цикла увеличивается с каж-дым выполнением.
Обращение к ячейке массива с использованием переменной, определен-ной в цикле
Часть в круглых скобках ( ) определяет, как долго будет выполняться цикл.Начинается
с ключевого слова for.
В цикле объ-является переменная, которая будет использовать-ся в качестве индекса для обращения к ячейкам массива. Эта переменная используется только внутри цикла.
Тело цикла всегда заключается в фигурные скобки.
Тело цикла завер-шается фигурной скобкой.
var i=0;
do{
alert(my_arr2[i]);
i++;
}while (i<=5);
1 2
3
4
1
3
4
2
Тело цикла заключается в фигурные скобки.
Переменная цикла увели-чивается при каждом его выполнении.
Цикл начинается с ключе-вого слова do.
Цикл завершается ключе-вым словом while.
Öèêëû do...while
Цикл for:
1 2 3 4 2 3 4... ... ... ... ... ... ...
Одно выполне-ние цикла
Другое выполнение цикла
Цикл do...while:
1 3 4 2 3 4 2... ... ... ... ... ... ...
Одно выполне-ние цикла
Другое выполне-ние цикла
В цикле объявляется перемен-ная, которая будет использо-ваться в качестве индекса для обращения к ячейкам массива. Не забывайте, что эта пере-
менная может использоваться только внутри цикла.
Циклы под увеличительным стеклом
Если присмотреться к упоминавшимся разновидностям циклов, видно, что все они содержат четыре основных компонента, но в несколько ином порядке. Порядок сле-дования этих компонентов отражает основные различия между циклами.
дальше � 263
jquery и javascript
ДжимФрэнкДжо
Фрэнк: У нас есть массив объектов card, но нам ведь нужно из-влечь случайную карту при сдаче, верно?
Джо: Да, и к счастью, мы уже написали функцию getRandom в гла-ве 3. Она будет возвращать случайное число каждый раз, когда по-требуется извлечь карту из массива.
Джим: И что мы будем делать с этой картой?
Фрэнк: Информацию о ней нужно сохранить. Мы должны просум-мировать очки и определить, дошел игрок до 21 очка или нет.
Джо: И еще одна причина: одну карту нельзя сдать дважды, поэто-му мы должны убедиться в том, что карта не была сдана ранее.
Джим: Карты будут сохраняться в переменных?
Фрэнк: Лучше воспользоваться массивом...
Джо: Точно! Причем хранить сами карты необязательно; доста-точно хранить их индексы. По ним можно будет проверить, содер-жится ли карта в массиве использованных карт used_cards.
Джим: И как мы узнаем, содержится ли значение в массиве?
Фрэнк: При помощи вспомогательного метода jQuery с именем inArray.
Джо: Звучит разумно. Но мне кажется, что для этого нам стоит воспользоваться несколькими функциями. Нам понадобится слу-чайное число от 0 до 51; потом нужно проверить, не было ли оно использовано ранее. Если карта уже использована, повторяем по-пытку, а если нет — извлекаем из колоды соответствующую карту и сохраняем ее индекс. Также необходимо вывести изображение карты для игрока.
Джим: И как мы выведем изображение карты?
Фрэнк: Вообще-то изображения у нас уже есть, они упорядочены по мастям и типам, мы воспользуемся этими атрибутами объекта card для отображения графики на странице.
Джо: Точно. Мы создадим элемент DOM и присоединим его к эле-менту div my_hand, уже находящемуся на странице.
Фрэнк: Наши усилия по созданию объекта card уже окупаются… За дело!
Циклы позволят нам быстро переме-щаться по массиву карт. Этак мы быстро управимся с заданием... Что там дальше?
264 глава 6
игра в прятки с переменными
А если мы захотим узнать, в какой
ячейке массива haystack хранится
это значение?
Ïîèñê èãîëêè â ñòîãå ñåíà
Часто бывает нужно проверить, содержится ли некоторое значение в массиве или нет, например, чтобы избежать дублирования данных или предотвратить повторное включение значения в мас-сив. Например, это особенно важно при использовании массива для хранения покупательской корзины или списка предполагаемых покупок.
var index = $.inArray( value, array );
Создаем переменную для хранения возвращаемого значения функции.
Сокращенная запись jQuery
Вызов вспомогательного метода inArray
Искомое значение Массив, в котором
ищется значение
Где именно в нашем приложении следует проверять, использовалось ли ранее полученное значение?
jQuery предоставляет целый набор вспомогательных методов, которые позволяют более эффек-тивно решать типичные задачи. В частности, существуют функции для проверки типа браузера, используемого посетителем, для получения текущего времени, для слияния массивов, для удале-ния дубликатов из массивов и т. д.
Вспомогательный метод, который пригодится в нашей конкретной ситуации, называется inArray. Он возвращает позицию (индекс) ячейки, в которой был найден искомый элемент, если он был найден, конечно. Если найти значение в массиве не удалось, метод возвращает –1. Как и другие вспомогательные методы, inArray не требует передачи селектора, он вызывается прямо для функции jQuery или ее сокращения.
var haystack = new Array('hay', 'mouse', 'needle', 'pitchfork')
Создание массива со всякой всячиной
var needle_index = $.inArray( 'needle', haystack );
Искомое значение
Массив, в котором ищется значение
Мозговой
штурм
дальше � 265
jquery и javascript
Расставьте магниты так, чтобы сложить из них код функций для нашего приложения. В готовом коде
должны содержаться определения двух функций (deal и hit), а также слушателя события click для
элемента с идентификатором btnDeal и определение нового массива used_cards, в котором хра-
нится информация о сданных ранее картах.
дальше � 265
var used_cards = new ___________();
function ___________{
for(var i=0;i<2;i++){
hit();
}
}
function getRandom(num){
var my_num = Math.floor(___________________*num);
return my_num;
}
function __________{
var good_card = false;
do{
var index = ________________(52);
if( !$.inArray(index, ______________ ) > -1 ){
good_card = true;
var c = deck[ index ];
_____________[used_cards.length] = index;
hand.cards[hand.cards.length] = c;
var $d = $("<div>");
$d.addClass("current_hand")
.appendTo(_____________);
$("<img>").appendTo($d)
.attr( _______ , 'images/cards/' + c.suit + '/' + c.name + '.jpg' )
.fadeOut('slow')
.fadeIn('slow');
}
}__________(!good_card);
good_card = false;
}
$("#btnDeal").click( _____________(){
deal();
$(this).toggle();
});my_scripts.js
deal()
hit()
getRandom
used_cards
Array
used_cards
"#my_hand"
'src'
while
function
Math.random()
Развлечения с магнитами
266 глава 6
решение упражнения
Ниже приведен завершенный код функций deal и hit, а также код слушателя события click для
элемента с идентификатором btnDeal и определение массива used_cards, в котором хранится
информация об уже сданных картах.
var used_cards = new ___________();
function ___________{
for(var i=0;i<2;i++){
hit();
}
}
function getRandom(num){
var my_num = Math.floor(___________________*num);
return my_num;
}
function __________{
var good_card = false;
do{
var index = ________________(52);
if( !$.inArray(index, ______________ ) > -1 ){
good_card = true;
var c = deck[ index ];
_____________[used_cards.length] = index;
hand.cards[hand.cards.length] = c;
var $d = $("<div>");
$d.addClass("current_hand")
.appendTo(_____________);
$("<img>").appendTo($d)
.attr( _______ , 'images/cards/' + c.suit + '/' + c.name + '.jpg' )
.fadeOut('slow')
.fadeIn('slow');
}
}__________(!good_card);
good_card = false;
}
$("#btnDeal").click( _____________(){
deal();
$(this).toggle();
});
my_scripts.js
cards = new
___________
ar i=0;i<2;
deal()
__________
ood card =
hit()
__
y(index,
_ getRandom __(52);
______________ )__
__om _
used_cards
_____________Array
var c = deck[ i
_____________[u__
hand.cards[hand
used_cards
current_hand
_____________)__
ppendTo($d)
"#my_hand"
($ )
_______ ,__
t('slow')
($ )
'src'
}
__________(__
ood card =
while
_______ __________function
____________________Math.random()
Создаем массив для хранения использованных карт.
Используем цикл for для двукратного вызова функции hit.Снова функция getRandom!
Управляющая переменная цикла do…while
Проверяем, была ли использована только что отобранная карта, при помощи функции inArray.
Если карта уже использо-
вана, повторяем попытку.
Строим путь к изо-бражению из свойств объекта card.
Включаем индекс карты в массив used_cards.
Получаем карту из массива deck.
Функция deal вызывается в обработчике click.
Заставляем карту «миг-нуть» на экране.
Развлечения с магнитами. Решение
дальше � 267
jquery и javascript
Включите код из упражнения с магнитами в файл my_scripts.js (после определения массива deck), откройте страницу в браузере. Щелкните на изображении колоды, чтобы получить карты.
Как вы думаете, что следует использовать для хранения всей этой информации?
Конечно, мы можем сдать дополнительные карты из колоды при помощи уже написанной функции hit.Нам только придется придумать, как запускать эту функцию — по щелчку на кнопке или еще как-нибудь. Также появляется дополни-тельная проблема: необходимо запоминать и подсчитывать сданные карты, чтобы проверить возможный выигрыш или перебор.
Я пока сдаю только две карты. А значит, я почти всегда выигрываю! Но пусть игра будет честной. Сможе-те ли вы организовать сдачу допол-
нительных карт?
Тест-драйв
Мозговой
штурм
268 глава 6
полуфабрикаты HTML и CSS
Вы уже стали настоящим профессионалом по стилю и структуре страниц, так что мы просто приводим обновленный код файлов index.html и my_style.css для сравнения. После включения нового кода HTML и CSS на странице появляются новые элементы, вско-ре мы свяжем их с программным кодом.
<!DOCTYPE html>
<html>
<head>
<title>Head First Black Jack</title>
<link href="styles/my_style.css" rel="stylesheet">
</head>
<body>
<div id="main">
<h1>Click to reveal your cards</h1>
<h3 id="hdrTotal"></h3>
<h3 id="hdrResult"></h3>
<div id="my_hand">
</div>
<div id="controls">
<div id="btnDeal">
<img src="images/deck_small.jpg">
</div>
<div id="btnHit">
<img src="images/deck_small.jpg">
</div>
<div id="btnStick">
<img src="images/stick_small.jpg">
</div>
</div>
</div>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script src="scripts/my_scripts.js"></script>
</body>
</html>
index.html
>
#controls{
clear:both;
}
.current_hand{
float:left;
}
#my_hand{
clear:both;
border: 1px solid gray;
height: 250px;
width: 835px;
}
#btnHit, #btnStick, #btnRestart{
display:none;
float:left;
}
h3 {
display: inline;
padding-right: 40px;
}
my_style.css
Добавляем но-
вые элементы
для сдачи карт
и отказа.
Добавляем код CSS для новых элементов.
Готово к употреблению
дальше � 269
jquery и javascript
Используя приведенную ниже диаграмму UML, создайте «одноразовый» объект с именем hand. Свойство cards должно содержать новый пустой массив. Свойству current_total при-сваивается значение 0. Метод sumCardTotal должен перебирать все карты в свойстве cards, суммировать их значения и задавать полученную сумму как значение свойства current_total. Далее свойство current_total используется для задания значения элемента с идентифика-тором hdrTotal. Мы уже написали небольшую часть кода объекта за вас.
var hand = {
cards : new Array(),
current_total : 0,
sumCardTotal: function(){
}
};
В: Существуют ли другие типы циклов, о которых мне следует знать?
О: Да, существуют. Цикл while очень по-хож на do…while, но условие в нем про-веряется в начале. Также существует цикл for…in, который перебирает свойства объекта и последовательно возвращает их значения.
В: Итак, я запустил цикл на выполне-ние. Могу ли я прервать его в середине?
О: Да, при помощи очень простой коман ды: break. При выполнении этой команды в любой точке цикла его выполнение преры-вается, а управление передается команде, следующей за циклом.
В: А что такое appendTo? Раньше мы видели только append. Эти методы чем-то различаются?
О: При использовании append селектор, вызывающий метод, является контейнером, в который вставляется содержимое. С другой стороны, при использовании appendTo со-держимое задается до метода (либо в виде се-лекторного выражения, либо в виде разметки HTML, созданной «на месте») и вставляется в заданный контейнер.
hand
cardscurrent_total
sumCardTotal()
частоЗадаваемые
вопросы
Упражнение
270 глава 6
решение упражнения
var hand = {
cards : new Array(),
current_total : 0,
sumCardTotal: function(){
}
};
this.current_total = 0;
for(var i=0;i<this.cards.length;i++){
var c = this.cards[i];
this.current_total += c.value;
}$("#hdrTotal").html("Total: " + this.current_total );
Итак, теперь у нас имеется объект hand со свойством card (массив), и функция, которая перебирает массив card, получает ценность текущей карты и обновляет сумму очков.
Нет, это определенно нежелательно. По правилам, описанным в со-общении из клуба «Head First», победитель определяется по не-скольким различным критери-ям. Давайте еще раз вспомним эти критерии.
Если сумма очков игрока превыша-ет 21, то происходит перебор. Игрок проиграл, игра закончена.
1
Если сумма очков игрока равна точ-но 21, то игрок набрал блэкджек, игра закончена.
2
Если сумма очков не превышает 21, но игрок уже получил пять карт, то игра закончена, а игрок побеждает.
3
Если ни одно из этих условий не вы-полнено, игрок может потребовать сдачи следующей карты (или остано-вить сдачу).
4
Создаем новый массив для свойства card.
Задаем свойству current_
total значение 0.
Выводим сумму на экран в элементе hdrTotal.
Перебираем ячейки массива card.
Получаем текущую
карту из массива.
Прибавляем очки к current_total.
Но никто не сообщает мне результат игры. В итоге при-ложение сдаст мне все карты,
разве не так?
hand
cardscurrent_total
sumCardTotal()
дальше � 271
jquery и javascript
Ïîðà ïðèíèìàòü ðåøåíèå... ñíîâà!
В главе 3 были рассмотрены условные конструкции для выпол-нения разного кода в зависимости от решений, принимаемых в коде на основании уже имеющейся информации.
if( myBool == true ){
// Здесь что-то делаем!
}else{
// Иначе делаем что-то другое!
}
Проверяемое условие
Оператор проверки
равенства
Начало условной команды if
Переменная JavaScriptКод, который должен выпол-няться, если условие истинно.
Оказывается, существует возможность проверки сразу не-скольких условий. Для этого следует объединить if и else в составную команду else if. Давайте посмотрим, как это дела-ется.
if( myNumber < 10 ){
// Здесь что-то делаем!
}else if( myNumber > 20 ){
// Иначе делаем что-то другое!
}else{
// Наконец, делаем что-то третье!
}
Проверяемое условие
Другое проверяемое условие
Где в нашем коде вы бы использовали конструкцию if / else if / else?
Мозговой
штурм
272 глава 6
то или это... или что-то еще!
Îïåðàòîðû ñðàâíåíèÿ è ëîãè÷åñêèå îïåðàòîðû
Условные конструкции (такие как if/else или do…while) должны принимать правильное решение на основании проверяемого условия. Для этого в них используются специальные операторы сравнения и логические операторы. В JavaScript существуют семь разных операторов сравнения и три логических оператора, а также оператор сокращенной записи конструкции if/else, называемый тернарным оператором. Некоторые из этих операторов уже встреча-лись нам ранее, а ниже приведен полный список.
Ðàâåíñòâî
a == b
Íåðàâåíñòâî
a != b
Ìåíüøå
a < b
Áîëüøå
a > b
Îòðèöàíèå
!a
Ìåíüøå ëèáî ðàâíî
a <= bÁîëüøå ëèáî ðàâíî
a >= b
Îïåðàòîðû ñðàâíåíèÿ
Ëîãè÷åñêèå îïåðàòîðû
Òî÷íîå ðàâåíñòâî
a === b
Èëè
a || b
È
a && b
Истина, если значение a равно b
Истина, если значение
a не равно b
Истина, если зна-чение a меньше b
Истина, если a меньше ИЛИ равно bИстина, если зна-чение a больше b
Истина, если a больше ИЛИ равно b
Истина, если значение a равно b и оба значения имеют одинаковый тип
Истина, если значение aложно илине существует (для элементов DOM)
Истина, если истинно хотя бы одно из двух значений a и b
Истина, если зна-чения a и b истинны одновременно
дальше � 273
jquery и javascript
Измените объект hand так, чтобы он проверял значение свойства current_total
на соответствие критериям игры (если забыли правила, вернитесь и перечитайте
исходное сообщение). Ниже приведен существующий объект, а также основа кода,
который вам необходимо написать.
var hand = {
cards : new Array(),
current_total : 0,
sumCardTotal: function(){
this.current_total = 0;
for(var i=0;i<this.cards.length;i++){
var c = this.cards[i];
this.current_total += c.value;
}
$("#hdrTotal").html("Total: " + this.current_total );
if(this. > 21){
$("#btnStick").trigger("click");
$("#hdrResult").html("BUST!");
} (this.current_total ){
$("#btnStick").trigger("click");
$("#hdrResult").html("BlackJack!");
}else if( .current_total 21 this.cards.length == 5){
$("#btnStick").trigger("click");
$("#hdrResult").html("5 card trick!");
}
// Продолжаем игру! :)
}
}
};
my_scripts.js
Возьми в руку карандаш
274 глава 6
решение упражнения
В метод sumCardTotal включена логика проверки очков сдан-
ных карт. Даже в этом простом приложении количество условных
и логических операторов получается весьма значительным.
var hand = {
cards : new Array(),
current_total : 0,
sumCardTotal: function(){
this.current_total = 0;
for(var i=0;i<this.cards.length;i++){
var c = this.cards[i];
this.current_total += c.value;
}
$("#hdrTotal").html("Total: " + this.current_total );
if(this.current_total > 21){ $("#btnStick").trigger("click");
$("#hdrResult").html("BUST!");
}else if(this.current_total == 21){
$("#btnStick").trigger("click");
$("#hdrResult").html("BlackJack!");
}else if(this.current_total <= 21 && this.cards.length == 5){ $("#btnStick").trigger("click");
$("#hdrResult").html("BlackJack - 5 card trick!");
}else{ // Продолжаем игру! :)
}
}
};
Проверяем условие:
значение current_total
больше 21.
Проверяем условие: равно ли свойство current_total 21
Проверяем условие: свойство current_total меньше либо равно 21 и игрок уже получил 5 карт.
В противном случае не делаем ничего!
my_scripts.js
Возьми в руку карандаш Решение
дальше � 275
jquery и javascript
Но мы пока не можем вызвать новые функции, потому что они
существуют сами по себе, верно?
Да, работа еще не закончена.В разметке HTML есть все необходимое для сдачи начальных карт, получения очередной карты и завершения игры. Просто эти возможности еще не включены в работу программы. И не забывайте, что при каждой сдаче новой карты необходимо вы-зывать метод суммирования очков.
Расставьте магниты так, чтобы у вас получилась функция, добавляющая несколько слушателей со-
бытий в приложение. Слушатели должны подключаться к элементам с идентификаторами btnHit
и btnStick. Кнопка btnHit должна сдавать очередную карту, а кнопка btnStick — останавливать
игру. Также после сдачи каждой карты должен вызываться метод sumCardTotal. Мы также включили
завершающий фрагмент функции hit, в который тоже необходимо внести изменения.
}while(!_______________);
good_card = false;
hand.___________________();
}
$("#btnDeal").click( _____________(){
deal();
$(this).toggle();
$("#btnHit")._____________();
$("#btnStick").toggle();
});
$("______________").click( function(){
hit();
});
$("#btnStick").click( function(){
$("#hdrResult").html(______________);
});
toggle
function
sumCardTotal
#btnHit
'Stick!'
good_card
my_scripts.js
Развлечения с магнитами
276 глава 6
решение упражнения
}while(!_______________);
good_card = false;
hand.___________________();
}
$("#btnDeal").click( _____________(){
deal();
$(this).toggle();
$("#btnHit")._____________();
$("#btnStick").toggle();
});
$("______________").click( function(){
hit();
});
$("#btnStick").click( function(){
$("#hdrResult").html(______________);
});
my_scripts.js
В: Существуют ли другие способы сравнения значений в JavaScript?
О: Существуют, впрочем, это не столько способ сравнения значений как таковой, а скорее способ принятия решений в зави-симости от значений переменных. Мы имеем в виду конструкцию switch, которая может проверять много разных условий. Если вам приходится писать длинные серии команд if / else if / else, их часто удается заменить конструкцией switch.
В: Вы упоминали о сокращенной форме команды if/else. Как она выглядит?
О: При использовании так называемого тернарного оператора усло-вие отделяется от выполняемого действия вопросительным знаком:
a > b ? код_true : код_false
Следующий код добавляет слушателей событий к кнопкам, а также вызывает
метод sumCardTotal после каждой сдачи карты.
();
_____________
.toggle();
toggle
___ __(_____ __function
ard = false;
____________ __________sumCardTotal
_____________
hit();#btnHit
____________)'Stick!'
_______________)
d = false;d = false;
good_cardЦикл выполняется,
пока не найдена подходящая карта.
В конце hit вычисляется сумма очков текущей руки.
Кнопка сдачи двух исходных карт скрывается, две другие кнопки отображаются.
Задаем выводимое
сообщение.
Сдаем две исходные карты.
Запросить одну карту.
Развлечения с магнитами. Решение
частоЗадаваемые
вопросы
дальше � 277
jquery и javascript
Включите весь новый код в файл my_scripts.js после функции hit (не забудьте обновить завершающий фрагмент самой функции hit). Откройте страницу в своем любимом браузере.
Джим Фрэнк Джо
Фрэнк: Не торопись. Нам еще нужно реализовать возмож-ность сброса, чтобы после окончания партии игрок мог на-чать игру заново без перезагрузки страницы.
Джо: Также необходимо проследить за тем, чтобы игроки не получали карты из предыдущих раздач. Из массивов нужно все удалить.
Джим: Но как мы это сделаем? Мы динамически добавляли элементы HTML, включали в массивы новые значения. И те-перь это все нужно стереть?
Фрэнк: Да. Способы решения этих задач слегка различаются, но нам действительно придется все стереть.
Джо: Кажется, я знаю! В jQuery для очистки содержимого элементов используется метод empty. Для очистки массивов существует несколько решений, но не все они одинаково рабо-тают во всех браузерах. Какой же способ лучше подойдет нам?
Ну что, готово?
Тест-драйв
278 глава 6
с чистого листа
Ñòèðàíèå èíôîðìàöèè â jQuery
Помните, как в главе 2 мы использовали метод jQuery remove для безвозвратного удаления конкретного элемен-та и всех его потомков из DOM? Такое решение отлично работает, если вы хотите удалить родительский элемент. Но если основной элемент должен остаться на своем ме-сте, а вы хотите только стереть его содержимое, лучше воспользоваться методом jQuery empty. Этот метод, как и remove, требует указания селектора, но элемент, для кото-рого он был вызван, остается на своем месте.
body
div id="main"
div id="my_hand"
div class=
"current_hand"div class=
"current_hand"
$("#my_hand").empty();
Текущая структура страницы
Часто мы используем jQuery для того, чтобы нам не прихо-дилось писать несколько строк кода JavaScript. К счастью, некоторые операции выполняются в JavaScript так же про-сто, как в jQuery; это как раз один из таких случаев. Син-таксис слегка отличается, но конечный результат остается неизменным, а вам не приходится отслеживать свою теку-щую позицию в DOM. Для очистки массива в JavaScript до-статочно сделать свойство length равным 0:
À â JavaScript åùå ïðîùå
used_cards.length = 0;
Проще простого, верно?
Итак, нам осталось выбрать то, что нужно стереть?
Да, но порядок стирания информации тоже важен.
Новая рука сдается при перезапуске, поэтому мы должны сначала все стереть и только потом сдать новую руку. Также необходимо обеспечить обра-ботку щелчков еще одним элементом, чтобы пере-дать управление нашему коду.
Элементы, которые мы хотим удалить
дальше � 279
jquery и javascript
Включите в файл index.html новый элемент div (по аналогии с другими управляющими
элементами div), присвойте ему идентификатор btnRestart. Разместите в нем элемент
изображения с источником restart_small.jpg из папки images.
Также включите в файл my_scripts.js слушателя события click для элемента btnRestart.,
который очищает элемент my_hand, массив used_cards и массив cards в объекте hand.
Кроме того, он должен отображать новый элемент div с идентификатором result и свой
элемент div, стирать разметку HTML элементов hdrResult, а в завершение отображать
элемент btnDeal и инициировать для него событие click.
<div id="btnStick">
<img src="images/stick_small.jpg">
</div>
<div id=" "><img src="" id="imgResult">
</div>
</div>
<script src="scripts/jquery-1.6.2.min.js"></script>
index.html
$("#hdrResult").html('Stick!');
});
$("#btnRestart").click( function(){
.toggle();
$(this).
$("#my_hand").
$("#hdrResult").html('');
used_cards. = 0;
.length = 0;
hand. = 0;
$("#btnDeal").toggle()
. ('click');
});
my_scripts.js
Возьми в руку карандаш
280 глава 6
решение упражнения
Итак, у нас есть кнопка сброса, которая возвращает все элемен-
ты в исходное состояние. Теперь немного волшебства JavaScript
со свойством length, и дело сделано!
<div id="btnStick">
<img src="images/stick_small.jpg">
</div>
<div id="btnRestart"> <img src="images/restart_small.jpg"> </div> <div id="result"><img src="" id="imgResult"></div> </div>
</div>
<script src="scripts/jquery-1.6.2.min.js"></script>
index.html
$("#hdrResult").html('Stick!');
$("result").toggle();
});
$("#btnRestart").click( function(){
$("#result").toggle(); $(this).toggle(); $("#my_hand").empty(); $("#hdrResult").html('');
used_cards.length = 0; hand.cards.length = 0; hand.current_total = 0;
$("#btnDeal").toggle()
.trigger('click');});
my_scripts.js
Кнопка сброса начи-нает игру заново.
Результат делается более наглядным.
Все элементы
возвращаются
в исходноесостояние.
Имитируем щелчок на элементе btnDeal.
Возьми в руку карандаш Решение
дальше � 281
jquery и javascript
Добавьте событие click для элемента btnRestart в файл my_scripts.js. Также не забудьте включить дополнительную разметку HTML в файл index.html.
Как здорово! Почти то, что я хотела... Только одна мелочь: нельзя ли сделать отображение результата более эффектным и интересным? Извини, что надоедаю со своими просьбами.
Тест-драйв
282 глава 6
все любят победителей
if(this.current_total> 21){
$("#btnStick").trigger("click");
$("#imgResult").attr('src','images/x2.png');
$("#hdrResult").html("BUST!")
.attr('class', 'lose');
}else if(this.current_total == 21){
$("#btnStick").trigger("click");
$("#imgResult").attr('src','images/check.png');
$("#hdrResult").html("BlackJack!")
.attr('class', 'win');
}else if(this.current_total <= 21 && this.cards.length == 5){
$("#btnStick").trigger("click");
$("#imgResult").attr('src','images/check.png');
$("#hdrResult").html("BlackJack - 5 card trick!")
.attr('class', 'win');
}else{}
$("#hdrTotal").html("Total: " + this.current_total );
}
};
function end(){
$("#btnHit").toggle();
$("#btnStick").toggle();
$("#btnRestart").toggle();
}
$("#btnStick").click( function(){
$("#hdrResult").html('Stick!')
.attr('class', 'win');
$("#result").toggle();
end();
});
×òîáû áûëî êðàñèâåå
Задание!
Включите в файл my_scripts.js новую функцию end, которая вызывается кнопкой btnStick, а также внесите изменения в логике sumCardTotal. Обновленную версию файла my_style.css можно загрузить по адресу:http://thinkjquery.com/chapter06/end/styles/my_style.css.
Назначаем атри-
буту src элемента
imgResult изображение
в зависимости от
результата игры.
Переключаем состояние
всех элементов управле-
ния для завершения игры.
Вызываем функцию end для завершения игры (после отказа от сдачи карты). my_scripts.js
Задаем класс заго-ловка в зависимости от результата игры.
дальше � 283
jquery и javascript
Обновите код метода sumCardTotal объекта hand в файле my_scripts.js. Также не забудьте загрузить новую версию файла my_style.css и установить ее на место старой.
Потрясающе! Великолепно! Теперь посетители клуба «Head
First» смогут провести время за игрой в блэкджек!
Тест-драйв
284 глава 6
ваш инструментарий jquery и javascript
Âàø èíñòðóìåíòàðèé jQuery è JavaScript
Глава 6 осталась позади. В ней ваш творческий инструментарий расширился: в нем появились объекты JavaScript, массивы и циклы.
Объекты JavaScript
Автономное создание и исполь-
зование конструкторов.
Использование объектов и вызов
конструктора
Массивы
Создание массивов
Сохранение значений в ячейках
Добавление элементов в массив
Обновление содержимого массива
Циклы
Цикл for
Цикл do...while
Логические операторы
Операторы сравнения
jQuery.empty
$.inArray — вспомогательный метод
.attr
.trigger
ГЛА
ВА 6
Хочу функцию «СделатьУборку»...
Пользовательские функции для пользовательских эффектов7
Что будем делать?
От объединения пользовательских эффектов jQuery с функциями JavaScript ваш код (и ваши веб-приложения) становится более эффективным и более мощным. В этой главе мы займемся совер-шенствованием эффектов jQuery посредством обработки событий браузера, использования временных функций и улучшения общей структуры и возможностей повторного использования пользовательских функций JavaScript.
286 глава 7
ой-ой...
Веб-приложение «Собери монстра» из главы 5 пользовалось большим успехом у детей и родите-лей. Но похоже, где-то допущена ошибка, из-за которой с эффектом молний возникают проблемы. Джилл из DoodleStuff сообщает о проблемах, а заодно просит доработать приложение.
Мы обнаружили, что когда поль-зователь открывает в браузере новую вкладку,
оставляя приложение «Собери монстра» открытым в другой вкладке, при возвращении на старую вкладку молнии бьют непрерывно. Кажется, с приложением
что-то не так!
Íàäâèãàåòñÿ áóðÿ
Попробуйте воспроизвести проблему. Что произошло с молниями? Почему после перехода на другую вкладку исчезли паузы между разрядами?
Когда посетитель запускает при-ложение «Собери монстра»…
…а потом открывает новую вкладку, остается на ней на несколько минут…
…а потом возвращается на вкладку приложения «Собери монстра», молнии непре-рывно сверкают, словно эффекты не поспевают друг за другом.
Джилл, директор
по контролю ка-
чества
Мозговой
штурм
дальше � 287
пользовательские функции
Ìû ñîçäàëè ìîíñòðà... ôóíêöèþ-ìîíñòðà
Функция сверкания молнии, написанная нами в главе 5, таит скрытый подвох. Она про-должает работать непрерывно, даже если пользователь ушел со страницы. А когда пользо-ватель возвращается на вкладку, таймер пытается наверстать упущенное время и быстро перерисовывает молнию на экране. Похоже, таймер работает не так, как мы хотели. Что же произошло?
В главе 5 нам был нужен механизм многократного вызова метода с за-держкой. Решая эту задачу, мы незаметно для себя создали новую про-блему: функция продолжает выполняться и тогда, когда окно теряет фокус (то есть когда посетитель открывает новую вкладку, покидая текущую страницу).
function lightning_one(t){ $("#lightning1").fadeIn(250).fadeOut(250); setTimeout("lightning_one()",t);};
Метод setTimeout приказывает
интерпретатору JS выполнить
функцию, а затем повторить ее
выполнение с некоторой задержкой.
В JavaScript функция обычно определяется в одном месте, а вызыва-ется в другом. В дан-ном случае мы вызываем функцию из нее самой.
Задержка в миллисекундах
Функция, которая бесконечно и бесконтрольно запускает сама себя? Слишком сложно и небезо-пасно! Как вернуть происходящее
под контроль?
Здесь мы указываем ин-терпретатору JS, что функция должна вызывать сама себя снова и снова.
С функциями, вызывающими сами себя, нужно быть очень осторожным.
Бесконечные циклы могут поглощать ресурсы системы, а это вызовет сбой в браузере посетителя.
Будьте осторожны!
288 глава 7
один объект правит всеми
Óïðàâëåíèå âðåìåííûìè ýôôåêòàìè
К счастью, анимацией сверкания молний можно управлять при помощи объекта JavaScript’s window. Объект window создается каждый раз, когда посетитель открывает в браузере новое окно; на базе этого объекта реализованы многие полезные функции jQuery и JavaScript. В мире JavaScript объект window является глобальным. Иначе говоря, он находится на верхнем уровне иерархии JavaScript.
Допустим, вы открыли в браузере три вкладки. Браузер создает для каждой вкладки от-дельный объект window. Это такой же объект, как и те, с которыми мы работали в гла-ве 6; он тоже обладает свойствами, обработчиками событий и методами. И эти объекты чрезвычайно удобны: при помощи обработчиков событий onblur и onfocus объекта window можно узнать, какие операции выполняются пользователем на уровне браузера.
Интерпретатор JavaScript использует объект window для представления окна, от-крытого в браузере.
Каждый раз, когда поль-зователь открывает новую вкладку, страницу или фрейм, создается новый объект window.
Браузер Объект window
Браузер
Объект window Объект window Объект window
Объект window также поддерживает методы работы с таймером, которые мы можем исполь-зовать в пользовательских функциях. У объекта window много методов, но нас сейчас интере-суют только эти методы, необходимые для ис-правления ошибки с молниями.
Когда вы щелкае-те на этом окне, браузер передает ему «фокус» (со-бытие onFocus).
Теперь фокус принадлежит этому окну.Если щелкнуть на другом окне, то ис-ходное окно теряет «фокус» (событие onBlur).
Не путайте обработ-чики событий onblur и onfocus объекта JavaScript window с методами jQuery blur и focus.
Методы jQuery blur и focus связываются с полями форм HTML и другими элементами, но не с объектом window.
Будьте осторожны!
дальше � 289
пользовательские функции
Соедините каждое свойство, обработчик события или метод окна window с его описанием.
Свойство объекта window для чтения или задания имени окна.
Свойство объекта window, ссыла-ющееся на основное содержимое загруженного документа.
Обнаруживает, когда окно полу-чает щелчок, нажатия клавиш или другой ввод.
Обнаруживает, когда окно теряет фокус.
Метод объекта window, исполь-зуемый для отмены задержки перед вызовом.
Метод объекта window, задаю-щий задержку между повторяю-щимися выполнениями функции или другой команды.
Метод объекта window, задаю-щий задержку перед выполнени-ем функции или другой команды.
window.name
window.onfocus
window.setTimeout()
window.setInterval()
window.clearTimeout()
window.clearInterval()
window.onblur
window.history
window.document
Свойство объекта window для обращения к URL-адресам, кото-рые ранее загружались в окне.
Метод объекта window, отменя-ющий задержку между повторны-ми вызовами.
Кто и что делает?аеааеееееееееееееееее
290 глава 7
решение упражнения
window. name
window. onfocus
window. setTimeout()
window. setInterval()
window.clearTimeout()
window. clearInterval()
window. onblur
window. history
window. document
Обработчики событий onfocus и onblur объекта window обнаруживают полу-чение/потерю фокуса окном, но как что-то сделать в ответ на эти события?
Свойство объекта window для чтения или задания имени окна.
Свойство объекта window, ссыла-ющееся на основное содержимое загруженного документа.
Обнаруживает, когда окно полу-чает щелчок, нажатия клавиш или другой ввод.
Обнаруживает, когда окно теряет фокус.
Метод объекта window, исполь-зуемый для отмены задержки перед вызовом.
Метод объекта window, задаю-щий задержку между повторяю-щимися выполнениями функции или другой команды.
Метод объекта window, задаю-щий задержку перед выполнени-ем функции или другой команды.
Свойство объекта window для обращения к URL-адресам, кото-рые ранее загружались в окне.
Метод объекта window, отменя-ющий задержку между повторны-ми вызовами.
Кто и что делает?аеааеееееееееееееееее
Мозговой
штурм
Решение
дальше � 291
пользовательские функции
Îáðàáîòêà ñîáûòèé áðàóçåðà â onblur è onfocus
Итак, мы знаем, что в window.onfocus можно определить, когда окно получает фокус (то есть посетитель активизирует страницу или передает окну ввод с кла-виатуры или мыши), а в window.onblur можно обработать потерю фокуса актив-ным окном. Но что нужно сделать для обработки этих событий? Методам onfocus и onblur следует присвоить ссылку на функцию.
window.onblur = blurResponse;
function blurResponse(){
}
Оператор присваивания
Опре-деление функции
window.onfocus = focusResponse;
function focusResponse(){
}
Ссылкана функцию
Оператор присваивания
Опре-деление функции
То, что должно происходитьв ответ на собы-тие браузера.
Давайте опробуем обработчики событий onfocus и onblur объекта window в деле. Найдите в файлах главы 7 папку с именем window_tester. Загрузите файл window_tester.html из этой папки в своем любимом браузере. Откройте вторую вкладку и поэкспериментируйте с переключением между двумя вкладками.
Перед нами наглядный пример того, какую пользу приносит написание пользова-тельских функций. Имеется объект window, содержащий гору информации о том, что пользователь делает в браузере; вы пишете пользовательскую функцию, которая работает с данными, полученными от объекта. Получается, что при обработке собы-тия можно делать абсолютно все, что угодно, главное написать для этого подходящую пользовательскую функцию...
Ссылкана функцию
Тест-драйв
292 глава 7
тест-драйв
Загрузите файл window_tester.html, откройте вторую вкладку и попро-буйте переключаться между окнами, попеременно щелкая на них.
Открываем файл window_tester.html в одном окне.
Открываем вторую вкладку.
При переключениях
между окнами сцена-
рий сообщает о по-
лучении и потере
фокуса.
При помощи информации, полученной от объекта window, можно остановить молнии, когда посетитель покидает окно приложения «Собери монстра», и продолжить отображение эффекта после его возвращения.
Тест-драйв
дальше � 293
пользовательские функции
Сложите из магнитов определения функций для обработчиков onblur и onfocus. Первая
функция останавливает сверкание молнии, когда браузер теряет фокус (она называется
stopLightning). Другая функция снова запускает эффект при получении фокуса браузером
(ей присваивается имя goLightning). Код функций пока писать не нужно, просто разложите
магниты с комментариями (начинающимися с //) внутри каждой функции.
window.onfocus
=
=
stopLightning;
//Код остановки молний
//Код запуска молний
goLightning;
function
};
stopLightning(){
function
};
goLightning window.onblur
(){
Развлечения с магнитами
294 глава 7
решение упражнения
Ниже приведены объявления функций для обоих обработчиков событий объекта window.
window.onfocus
=
=
stopLightning;
//код остановки молний
//Код запуска молний
goLightning;
function
};
stopLightning (){
function
};
goLightning
window.onblur
(){
Но пока в этих функциях нет ничего, кроме комментариев. Функции должны что-то делать! Может, просто скопиро-
вать сюда код старых функций?
Верно. Функции ничего не делают... пока. Не торопитесь копировать старый код. Эффект свер-кания молнии удобнее реализовать с использовани-ем методов работы с таймером объекта window.
Наши функции при-
сваиваются собы-
тиям window.onblur
и window.onfocus.
При вызове этой функции молнии оста-навливаются.
А при вызове этой функции они начинают сверкать снова.
Развлечения с магнитами. Решение
дальше � 295
пользовательские функции
Ìåòîäû ðàáîòû ñ òàéìåðîì îïðåäåëÿþò âðåìÿ âûïîëíåíèÿ ôóíêöèé
И в JavaScript, и в jQuery имеются методы для выполнения функций по таймеру. У объекта JavaScript window есть четыре метода для работы с таймером: setTimeout, clearTimeout, setInterval и clearInterval. jQuery поддерживает метод delay. Давайте поближе позна-комимся с этими методами и их возможностями.
Какой из этих методов подойдет для исправления функции goLightning?
Напишите для каждого метода, пригодится ли он в нашей ситуации, и объясни-
те, почему вы его выбрали (или не выбрали).
Метод Будем исполь-
зовать?
Почему?
setTimeout
setInterval
delay
setTimeout(myFunction, 4000); slideDown().delay(5000).slideUp();setInterval(repeatMe, 1000);
Функция, вы-зываемая по истечении тайм-аута
Задержка таймера (в миллисе-кундах)
Интервал между вызо-вами функ-ции (в мил-лисекундах)
Функция, вызываемая после исте-чения каж-дого интер-вала
Выполнение таких цепо-чек в jQuery называется «очередью эффектов».
В данном при-мере метод delay вставляет 5-се-кундную задержку между эффектами slideUp и slideDown..
setTimeout setInterval delay
Ìåòîäû JavaScript Ìåòîä delay jQuery
Я определяю вре-мя, через которое
должна выпол-няться функция.
Я приказываю функции выпол-
няться снова через заданный промежу-
ток времени.
Я добавляю паузу между эффекта-ми, объединен-ными в цепочку.
Возьми в руку карандаш
296 глава 7
решение упражнения
Итак, setInterval лучше всего подой-дет для функции goLightning, но функция
stopLightning должна остановить таймер. Как бы это сделать? Может методом
clearInterval?
Хороший вопрос! Метод clearInterval останавливает вызов функции по таймеру, запущенный методом setInterval. При вызове clearInterval необходимо передать параметр. Вот как это делается:
myInterval = setInterval(repeatMe, 1000);
clearInterval(myInterval);
Метод Будем исполь-
зовать
Почему?
setTimeout Нет Метод setTimeout предназначен для создания задержки перед однократным выполнением функции.
setInterval Да Метод setInterval предназначен для многократного вы-полнения функции с заданными интервалами. Именно это нам и нужно в эффекте с молниями.
delay Нет Метод delay хорошо подходит для создания серий эф-фектов, но у него нет средств планирования отло-женного запуска.
Какой из этих методов подойдет для исправления функции
goLightning? Вот наши ответы.
Присваивается переменной, идентифицирующей
метод setInterval.
Переменная пере-дается в параметре clearInterval.
Метод clearInterval останавливает таймер setInterval и прекращаетпериодическое выполнение.
Возьми в руку карандаш Решение
дальше � 297
пользовательские функции
Обнаруживает, когда текущее окно получает фокус, и вызывает метод goLightning.
Обнаруживает, когда текущее окно теряет фокус, и вызывает функцию stopLightning.
Выполняет функцию lightning_one каждые 4 секунды, с присваива-нием результата переменной int1.
Останавливает таймер и прекраща-ет повторение для int1.
Создает пятисекундную паузу между эффектами fadeIn и fadeOut.
Устанавливает задержку 4 секунды перед вызовом функции wakeUp.
window.clearInterval(int1);
$("#container #lightning1").fadeIn(250).delay(5000).fadeOut(250).;
int1 = setInterval( function() { lightning_one(); }, 4000 );
window.onblur = stopLightning;
Соедините каждый вызов метода с его описанием.
window.onfocus = goLightning;
setTimeout(wakeUp(),4000);
В: Метод setTimeout во всех браузерах работает одинаково?
О: Нет. Mozilla Firefox и Google Chrome работают так, как было описано выше («складывая» вызовы функций). Internet Explorer 9 продолжает вызывать функцию так, как предполагалось в главе 5. Это показывает, что проблемы с межбраузерной совместимостью возникают не только у веб-дизайнеров.
В: Можно ли использовать функции setInterval и setTimeout для чего-то другого, кроме объекта window?
О: К сожалению, нельзя. Это конкретные методы объ-екта window, и вызываться они могут только по ссылке на объект window. Однако возможен вызов методов без префикса «window»; браузер определит, что вызов нужно связать с текущим объектом window. Впрочем, префикс все же рекомендуется указывать.
частоЗадаваемые
вопросы
Кто и что делает?аеааеееееееееееееееее
298 глава 7
решение упражнения
window.clearInterval(int1);
$("#container #lightning1").fadeIn(250).delay(5000).fadeOut(250).;
int1 = setInterval( function() { lightning_one(); }, 4000 );
window.onblur = stopLightning;
Соедините каждый вызов метода с его описанием.
window.onfocus = goLightning;
setTimeout(wakeUp(),4000);
Ïèøåì ôóíêöèè stopLightning è goLightning
Теперь вы больше знаете о таймере, давайте посмотрим, как использовать эти методы в нашем коде.
Функция stopLightning вызывается
при потере фокуса браузером.
Функция goLightning вызывается при получении фокуса браузером.
Сброс таймеров для трех интер-валов. Нам понадобятся три вызова clearInterval. Знаете, почему?
Установка трех таймеров для трех интервалов. Да, здесь нам понадо-бятся три вызова setInterval.
Молнии запускаются при загрузке страницы.goLightning();
window. onblur = stopLightning;
window. onfocus = goLightning;
function stopLightning (){
//Код остановки молний
};
function goLightning (){
//Код запуска молний
};
Обнаруживает, когда текущее окно получает фокус, и вызывает метод goLightning.
Обнаруживает, когда текущее окно теряет фокус, и вызывает функцию stopLightning.
Выполняет функцию lightning_one каждые 4 секунды, с присваива-нием результата переменной int1.
Останавливает таймер и прекраща-ет повторение для int1.
Создает пятисекундную паузу между эффектами fadeIn и fadeOut.
Устанавливает задержку 4 секунды перед вызовом функции wakeUp.
Кто и что делает?аеааеееееееееееееееее
Решение
дальше � 299
пользовательские функции
Пора исправить недостатки приложения «Собери монстра». Заполните пропуски име-нами переменной, функции или метода. Если вы сомневаетесь, снова просмотрите код на двух предыдущих страницах. Мы заполнили некоторые пропуски за вас.
goLightning(); window.onblur = stopLightning; window.onfocus = goLightning; var int1, int2, int3 ; function goLightning(){ = ( function() { }, 4000 );
= ( function() { }, 5000 ); = ( function() { }, 7000 ); } function stopLightning() { window. ( ); window. ( ); window. ( ); } function { $("#container #lightning1").fadeIn(250).fadeOut(250); };
function { $("#container #lightning2").fadeIn(250).fadeOut(250); }; function { $("#container #lightning3").fadeIn(250).fadeOut(250); };
int1
int1
lightning_three();
lightning_one()
my_scripts.js
Упражнение
300 глава 7
решение упражнения
goLightning(); window.onblur = stopLightning; window.onfocus = goLightning; var int1, int2, int3 ; function goLightning(){ = ( function() { }, 4000 );
= ( function() { }, 5000 ); = ( function() { }, 7000 ); } function stopLightning() { window. ( ); window. ( ); window. ( ); } function { $("#container #lightning1").fadeIn(250).fadeOut(250); };
function { $("#container #lightning2").fadeIn(250).fadeOut(250); }; function { $("#container #lightning3").fadeIn(250).fadeOut(250); };
int1
int1
lightning_three();
lightning_one()
my_scripts.js
У нас появились две пользовательские функции, реагирующие на события onfocus и onblur объекта window (в них используются функции, написанные нами в главе 5).
clearIntervalclearInterval int2clearInterval int3
setInterval
setIntervalint2
setIntervalint3
lightning_one();
lightning_two();
lightning_two()
lightning_three()
Сброс таймеров для трех интервалов
Устанавливаем три разных таймера с тремя интервалами.
Определения трех функций.
Здесь вызывается функция lightning_one.
Затем вызываем
функцию lightning_two.
И последней вызывается
функция lightning_three.
Объявляем три переменные для хранения таймеров, чтобы при необходимости их можно было снова сбросить в браузере.
дальше � 301
пользовательские функции
Включите код с предыдущей страницы в файл сценария, откройте страницу в браузере и посмотрите, удалось ли нам решить проблему с эффектами молний.
Вносить все изменения и исправления в код, написанный для главы 5, было бы слиш-ком сложно; проще начать заново, с пустого файла сценария. Найдите в архиве кода, загруженного для книги, папку главы 7. В ней находится вложенная папка begin, которая имеет следующую структуру:
index.html
jquery-1.6.2.min.js
images scripts
my_scripts.js
styles
begin
Включите код с предыдущей страницы…
…в блок $(document).ready своего файла сценария.
$(document).ready(function(){
});//end doc.onready function
Откройте приложе-ние «Собери монстра» в окне браузера.
Откройте новую вкладку, оставайтесь на ней пару минут.
Затем вернитесь на исходную вкладку с приложением «Собери монстра». При возвра-щении первый эффект молнии должен запу-ститься только через четыре секунды.
Задание!
Тест-драйв
302 глава 7
приводим в порядок функции
var headclix = 0, eyeclix = 0, noseclix = 0, mouthclix = 0;
$("#head").click(function(){ if (headclix < 9){ $("#head").animate({left:"-=367px"},500); headclix+=1; } else{ $("#head").animate({left:"0px'},500); headclix = 0; } }); $("#eyes").click(function(){ if (eyeclix < 9){ $("#eyes").animate({left:"-=367px"},500); eyeclix+=1; } else{ $("#eyes").animate({left:"0px"},500); eyeclix = 0; } }); $("#nose").click(function(){ if (noseclix < 9){ $("#nose").animate({left:"-=367px"},500); noseclix+=1; } else{ $("#nose").animate({left:"0px"},500); noseclix = 0; } });//end click $("#mouth").click(function(){ if (mouthclix < 9){ $("#mouth").animate({left:"-=367px"},500); mouthclix+=1; } else{ $("#mouth").animate({left:"0px"},500); mouthclix = 0; } });//end click
my_scripts.js
Отличная идея. У нас несколько почти одинаковых функций для обработки щелчков, которые можно заменить одной универсальной функцией.
Раз уж мы занялись исправлениями, почему бы не избавиться от однообразных функций,
написанных в главе 5?
Нельзя линаписать одну функцию, которую можно будет использовать в каждом из этих случаев?
Здесь лучше подойдет другая структура дан-ных, которая содержит несколько переменных.
дальше � 303
пользовательские функции
var clix = __________; // head,eyes,nose,mouth
$("#head").click( function(){
_______________ });//end click function $("#eyes").click( function(){
_______________ } );//end click function $("#nose").click( function(){
_______________ });//end click function $("#mouth").click( function(){
_______________ });//end click function function moveMe(________){ if (__________ < 9){ $(obj).animate({left:"-=367px"},500); clix[i] = clix[i]+1; }else{ clix[i] = 0; $(______).animate({left:"0px"},500); } }
[0,0,0,0]
moveMe(2, this);
moveMe(3, this);
moveMe(1, this);
moveMe(0, this);
clix[i]
i, obj
obj
В коде на предыдущей странице найдите фрагменты, общие для разных аспектов приложения. Сло-
жите из магнитов код универсальной функции moveMe, которая вызывается при щелчке на любой
из подвижных частей изображения. В первом параметре moveMe передается индекс массива clix,
а во втором — ссылка на часть изображения, на которой был сделан щелчок.
my_scripts.js
Развлечения с магнитами
304 глава 7
решение упражнения
var clix = __________; // head,eyes,nose,mouth
$("#head").click( function(){
_______________ });//end click function $("#eyes").click( function(){
_______________ } );//end click function $("#nose").click( function(){
_______________ });//end click function $("#mouth").click( function(){
_______________ });//end click function function moveMe(________){ if (__________ < 9){ $(obj).animate({left:"-=367px"},500); clix[i] = clix[i]+1; }else{ clix[i] = 0; $(______).animate({left:"0px"},500); } }
my_scripts.js
__________;[0,0,0,0]
_______________/end click function
moveMe(2, this);
_______________/end click function
moveMe(3, this);
_______________//end click function
moveMe(1, this);
_______________/end click function
moveMe(0, this);
__________$(obj).anclix[i]
________)i, obj
ix[i]______)obj
Итак, теперь у нас имеется одна универсальная функция, работающая с массивом.
Одна функция создает меньше проблем с сопровождением кода, в ней проще нахо-
дить и исправлять ошибки.
Универсальная функция moveMe снижает риск ошибок программи-рования и сокращает количество функций, которые вам придется сопровождать.
Дублирующаяся логика теперь сосредоточена в одном месте. Если в про-грамме обнару-жится ошибка, исправить ее будет проще и быстрее, чем в нескольких дубликатах.
Функция moveMe получает ссылку на ячейку массива clix. Эта инфор-мация может использоваться для отслеживания количества щелчков на каждом элементе.
Функции moveMe также переда-ется ссылка на текущий объект для выполнения анимации.
Преобразование набора пе-ременных в массив делает код более компактным.
Развлечения с магнитами. Решение
дальше � 305
пользовательские функции
Внешне страница приложе-ния нисколько не изменилась, но мы-то знаем, что код стал более эффективным, содержит меньше дубликатов и создает меньше проблем с сопровождением.
Включите код из упражнения с магнитами на предыдущей странице в файл my_scripts.js. Сохраните файл, откройте страницу index.html в бра-узере и убедитесь в том, что новая версия функции правильно обраба-тывает щелчки на разных частях лица монстра.
Тест-драйв
306 глава 7
молния ударяет дважды
Íîâàÿ ïðîñüáà
Мы получили несколько просьб. Дети хотят иметь кнопку, создающую случайное лицо монстра. Можно ли
встроить ее в приложение?.. А еще ино-гда хочется сбросить текущее изображе-
ние и начать все заново...
Джилл и вся группа контроля качества довольны вашими исправлениями. А раз уж им нравится ваша работа, они передают вам просьбу на расширение функциональности приложения от потенциальных клиентов.
Мне нравятся мои мон-стры... Но интересно по-смотреть, какие монстры получатся у компьютера.
дальше � 307
пользовательские функции
Мы уже не раз создавали функции, использующие генератор случайных чисел, так что сейчас вы уже стали настоящим специалистом по ним. Сейчас нам предстоит создать функцию для выполне-ния случайной анимации лица монстра. Давайте разделим общую задачу на серию меньших подза-дач. Начнем с определения текущей позиции в каждой полосе с изображениями.
Но на этот раз потребует-ся число от 1 до 10 (потому что каждая полоса состоит из 10 фрагментов).
Каждая часть лица монстра оказы-вается в случайной позиции, умножен-ной на ширину каждого фрагмента. Для случайного числа 7 целевая пози-ция равна 7 * 367, то есть 2569.
Текущая позиция вычисляется как количе-
ство щелчков, умноженное на расстояние
между частями лица на полосе (367 пик-
селов). В нашем примере текущая позиция
равна 2 * 367, то есть 734.
Нам потребуется отслежи-вать текущую позицию для каждой полосы изображений. Допустим, посетитель сей-час находится здесь.
Ñëó÷àéíûå ìîíñòðû
Получение случайного числа.1 Для каждой части лица выбирается случайная позиция.
2
От текущей позиции нужно перейти к целевой позиции, которая по сути является случайной позицией в полосе изображений. Операцию перемещения удобнее разбить на две части:
var my_num = Math.floor((Math.random()*5) + 5);
Так мы получали случайные числа в главах 2 и 3.
Хм, вас послушаешь, вроде бы все просто... Но что мы будем делать
с определением текущей позиции? Как узнать, какая часть лица отображает-ся на полосе, особенно если ее кто-то
уже прокручивал? Все проще, чем кажется на первый взгляд. Чтобы узнать, как это делается, просто переверните страницу.
308 глава 7
чем больше знаешь...
...è ôóíêöèÿ getRandom óæå ãîòîâà
function getRandom(num){
var my_random_num = Math.floor(Math.random()*num);
return my_random_num;
}
var current_position = clix[index] ;
Мы уже создавали функции для получения случайных чисел в главах 2, 3 и 6. Сейчас мы сможем использовать готовую функцию с минимальными изменениями.
К счастью, нам не потребуются ни новые переменные, ни новые функции. Текущая позиция опреде-ляется значением в соответствующей ячейке массива clix, в которой хранится информация, сколько раз пользователь щелкнул на каждой части лица монстра. Нам понадобится одна строка кода:
Функция getRandom получает в аргументе число…
Умножая Math.random на число, переданное в ар-гументе, мы генерируем случайное число в интер-вале от 0 до num.
…генерирует и возвраща-ет целое число. В данном случае генерируется число от 0 до 10.
num = 10;getRandom(num);
return my_random_num;
var my_random_num = Math.floor(Math.random()*num);
Ìû óæå çíàåì òåêóùóþ ïîçèöèþ...
Вызов дает значение целевой позиции (т. е. случай-ный фрагмент лица), к которой мы хотим перейти.
Переменной теку-щей позиции при-сваивается значение clix[index].
Функции, специализирующиеся на решении одной
задачи, иногда называют вспомогательными.
Передаем значение функции
Присваиваем значение переменной и передаем ее функции:1
Выполняем основную операцию функции:2
Возвращаем результат:3
дальше � 309
пользовательские функции
var w = 367; // Ширина одного фрагмента
var m = 10; // Количество фрагментов
$("#btnRandom").click( randomize );
$("#btnReset").click( );
function getRandom(num){
var my_random_num = Math.floor(Math.random()*num);
return my_random_num;
}
function randomize(){
$(".face").each(function(index){
var target_position = getRandom(m);
var current_position = clix[index] ;
clix[index] = target_position;
var move_to = target_position * w;
$(this).animate({left:"-="+move_to+"px"},500);
});
};
<header id="top">
<img src="images/Monster_Mashup.png" />
<button id="btnRandom">Randomize</button>
<button id="btnReset">Reset</button>
<p>Make your own monster face by clicking on the picture.</p>
</header>
Включите код, выделенный жирным шрифтом, в файлы index.html и my_scripts.js. В нем определяется функция, генерирующая слу-чайное изображение монстра, а также выводятся сообщения с информацией о целевой позиции (выбранной на основании слу-чайного числа) и текущей позиции (определяемой количеством щелчков, сделанных посетителем).
Переменной target_position присваивается результат вызова getRandom.
Обновляем clix[index], чтобы пользователь мог продолжать щелкать на частях лица мон-стра.
Переменной move_to при-сваивается случайная позиция, умноженная на ширину одного фрагмен-та на полосе.Выполняем пользователь-
ский код анимации пере-мещения полосы влево.
Определение случайной позиции для каждой ча-сти лица
index.html
my_scripts.js
В интерфейс нужно включить кнопки для генерирования случай-ного монстра и сброса.
Готово к употреблению
310 глава 7
тест-драйв
Включите код с предыдущей страницы в ваши файлы, откройте стра-ницу index.html в своем любимом браузере для тестирования функции randomize. Щелкните на кнопке Randomize 10–20 раз, чтобы тщательно протестировать новую функцию.
Ãåíåðàòîð ìîíñòðîâ ðàáîòàåò...
...íî òîëüêî íà íåñêîëüêèõ ïåðâûõ ùåë÷êàõ
На нескольких пер-вых щелчках гене-ратор монстров делает именно то, что требуется.
Конечно, зубы — главное,что есть у монстра, но остаться
без лица как-то не хочется!
Но через несколько щелчков начинаются какие-то проблемы.
Тест-драйв
дальше � 311
пользовательские функции
Повторные вызовы animate продолжают
смещать полосу изображений влево и вскоре
выводят ее за пределы видимости. Изобра-
жение, что называется, «уходит за край».
Части лица пропадают? Такого мы не про-граммировали. Они должны были попадать в случайную позицию! Может, мы оказались
слишком далеко?
Вы правы. У наших функций имеются непредвиденные побочные эффекты. Но скорее всего, эти функции делают в точности то, что мы написа-ли в своем коде. Давайте посмотрим, что мы могли упустить.
$(this).animate({left:-="+move_to+"px"},500);
Если пользователь продолжает щелкать на кнопке Randomize, полоса уйдет налево так дале-ко, что изображения перестанут отображаться на экране.
Помогите!Мы хотим обратно
в рамку!
Как вы думаете, что нужно сделать, чтобы поло-са изображений не уходила за край, а оставалась на случайных фрагментах монстра?
напряги мозги
312 глава 7
откуда и куда?
Ïåðåìåùåíèå îòíîñèòåëüíî òåêóùåé ïîçèöèè
Чтобы полоса изображений не выходила за край, а останавливалась на случайной части лица монстра (как было задумано), необходимо перемещать ее относительно текущей позиции. Для этого нужно вклю-чить в сценарий проверку текущей позиции и условную логику. Давайте разберемся подробнее.
Ñèòóàöèÿ 1: target_position > current_position
Функция getRandom вернула значение 5. Таким образом, переменной target_position присваивается значение 5, то есть она больше перемен-ной current_position. Мы должны написать логику для обработки этой ситуации.
Ñèòóàöèÿ 2: target_position < current_position
Далее пользователь щелкает на кнопке Randomize, которая генерирует случайное число в интервале от 0 до 9. Рассмотрим две принципиально возможные ситуации.
Пользователь находится на этом изображении. Текущая
позиция 2, потому что посетитель щелкнул дважды.
Функция getRandom вернула значение 1. Переменная target_position равна 1, то есть она меньше переменной current_position. Как вы думаете, какую логику следует применить в этом случае (по образцу условной логики из ситуации 1)?
target_position = 1 current_position = 2
Если переменная target_position меньше current_position, нужно
вычесть target_position из current_position и сместить полосу
изображений вправо вызовом animate({left:"+=".
target_position = 5Вычитая current_position из target_position, полу-чаем 3. Нужно переме-ститься на три позиции влево.
На сколько позиций нуж-но сместить полосу?
Вычитая target_position из current_position, по-лучаем 1. Необходимо сместиться на одну позицию вправо.
current_position = 2
Если переменная target_position variable больше current_position,
нужно вычесть current_position из target_position и сместить
полосу изображений влево вызовом animate({left:"-=".
0 1 3 5 7 94 6 822
0 1 3 5 7 94 6 822
0 1 3 5 7 94 6 822
дальше � 313
пользовательские функции
Ребус в бассейнеВыловите из бассейна фрагменты кода и расставьте их на пустых местах в коде.
Каждый фрагмент может использоваться только один раз; некоторые фраг-
менты могут остаться неиспользованными. Ваша задача — исправить
ошибку в функции, чтобы части лица монстра не оставались пустыми.
Внимание: каждый
фрагмент может
быть использован
не более одного
раза!
var w = 367;var m = 10;
function getRandom(num){ var my_random_num = Math.floor(Math.random()*num); return my_random_num;}function randomize(){ $(".face"). { var target_position = getRandom(m); var current_position = clix[index] ; clix[index] = target_position;
if( ) { var move_to = ( ) * w; $(this).animate( ); }else if( ){ var move_to = ( ) * w; $(this).animate( ); }else{ // Позиция не изменилась - ничего не делать. } });};
each(function(index)
target_position > current_position
target_position - current_position target_position + current_position
target_position == current_positiontarget_position < current_positioncurrent_position - target_position
{left:"+="+move_to+"px"},500
{left:"="+move_to+"px"},500
{left:"-="+move_to+"px"},500
314 глава 7
решение упражнения
Решение ребуса в бассейнеВыловите из бассейна фрагменты кода и расставьте их на пустых местах в коде.
Каждый фрагмент может использоваться только один раз; некоторые фраг-
менты могут остаться неиспользованными. Ваша задача — исправить ошибку
в функции, чтобы части лица монстра не оставались пустыми.
var w = 367;var m = 10;
function getRandom(num){ var my_random_num = Math.floor(Math.random()*num); return my_random_num;}function randomize(){
$(".face"). {
var target_position = getRandom(m);
var current_position = clix[index] ;
clix[index] = target_position;
if( ) {
var move_to = ( ) * w;
$(this).animate( );
}else if( ){
var move_to = ( ) * w;
$(this).animate( );
}else{
// Позиция не изменилась - ничего не делать.
}
});
};
each(function(index)
target_position > current_position
target_position < current_position
target_position - current_position
current_position - target_position{left:"+="+move_to+"px"},500
{left:"-="+move_to+"px"},500
target_position + current_position
target_position == current_position
{left:"="+move_to+"px"},500
Выполнить следующий код для каждого элемента класса face.
…вычесть target_position из current_position.
Эти фрагмен-ты оказались лишними.
...вычесть target_position из current_position.
Полоса изображений перемещается вправо. Для этого используется вызов animate({left:"+="...
Если переменная target_position больше current_position…
Полоса изображений перемеща-ется влево. Для этого исполь-зуется вызов animate({left:"-=".
Если переменная target_position меньше current_position...
дальше � 315
пользовательские функции
Совершенно верно.
Помните кнопку Reset в файле index.html несколько страниц назад? Осталось связать ее с пользовательской функцией сброса.
Разложите магниты по местам так, чтобы у вас получился код кнопки и пользо-
вательской функции сброса. Мы уже расставили часть магнитов за вас.
.animate({left:"0px"},500);({left:"0px"} 500);
.each(function(index){});
$(".face") $(this)
clix[index] = 0;
}
function reset(){
$("#btnReset").click( reset );
Функция генерирования случайных монстров работает отлично. Пора пере-ходить к функции сброса изображения
в исходное состояние?
Развлечения с магнитами
316 глава 7
решение упражнения
Вуаля! Всего несколько строк — кнопка сброса работает,
и монстра можно собирать заново.
.animate({left:"0px"},500);
.each(function(index){
});
$(".face")
Связываем пользова-тельскую функцию сброса с кнопкой.
Обнуляем массив clix.
$(this)
clix[index] = 0;
}
Определяем пользователь-скую функцию сброса.
Каждая полоса возвращается к началу, для чего ее свойству CSS left присваивается абсолютная по-зиция 0px.
Используем each, чтобы функция сбрасывала теку-щую позицию каж-дой части до 0.
function reset(){
$("#btnReset").click( reset );
В: Объект window существует во всех браузерах?
О: Да, все современные браузеры под-держивают объект window, с которым вы можете работать. Каждый объект window (по одному на каждую вкладку браузера) также имеет отдельный объект document, в который загружается веб-страница.
В: Почему перемещения выполняются относительно текущей позиции? Почему я не могу перейти туда, куда указывает случайное число?
О: Такое решение будет работать, но вам придется возвращать изображение в на-чальную позицию, а потом перемещать его в позицию, определяемую генератором случайных чисел. Это удваивает объем кода, который вам придется написать, и за-медляет работу приложения.
В: Как работает функция reset?
О: Функция reset просто перебирает все элементы с классом face и присваивает их свойству CSS left значение 0. Затем она обнуляет все ячейки массива clix, как на момент загрузки страницы.
Развлечения с магнитами. Решение
частоЗадаваемые
вопросы
дальше � 317
пользовательские функции
Ниже приведен весь код, написанный на предыдущих страни-цах. Если вы еще не сделали этого ранее, добавьте код, выде-ленный жирным шрифтом, в файл my_scripts.js и приготовьтесь к тестированию всех новых возможностей приложения.
Задание!
var w = 367; // Ширина одного фрагмента
var m = 10; // Количество фрагментов
$("#btnRandom").click( randomize );
$("#btnReset").click( reset );
function getRandom(num){
var my_random_num = Math.floor(Math.random()*num);
return my_random_num;
}
function randomize(){
$(".face").each(function(index){
var target_position = getRandom(m);
var current_position = clix[index] ;
clix[index] = target_position;
if( target_position > current_position ) {
var move_to = (target_position - current_position) * w;
$(this).animate({left:"-="+move_to+"px"},500);
}else if( target_position < current_position ){
var move_to = (current_position - target_position) * w;
$(this).animate({left:"+="+move_to+"px"},500);
}else{
// Позиция не изменилась - ничего не делать.
}
});
}
function reset(){
$(".face").each(function(index){
clix[index] = 0;
$(this).animate({left:"0px"},500);
});
} my_scripts.js
318 глава 7
хорошая работа!
Введите код с предыдущей страницы, откройте файл index.html в своем любимом брау-зере для тестирования функций randomize и reset. Щелкните на кнопке Randomize 10–20 раз, чтобы тщательно протестировать новую функцию. Время от времени щел-кайте на кнопке Reset, она тоже должна работать так, как задумано.
Âñå ðàáîòàåò!
Части лица монстра те-перь перемещаются влево-вправо, отчего приложение смотрится еще лучше.
А кнопка Resetвозвращает всев исходное состояние.
Тест-драйв
дальше � 319
пользовательские функции
«Ñîáåðè ìîíñòðà-2» — íàñòîÿùèé õèò!
Смотри, а у меня получилась Акуло-
Волко-Мумия!
Я только что собрала Свино-Ведьмо-Оборотня... Он будет главным героем повести, которую я сей-
час пишу.
Благодаря вашей работе приложение «Собери монстра» пользуется огромной популярностью!
Вы справились с проблемами и реализовали новые функции за рекордное время! Я уговорила
босса выплатить вам премиальные.
320 глава 7
ваш инструментарий jquery
Âàø èíñòðóìåíòàðèé jQuery
Глава 7 осталась позади. Ваш творческий инструмен-тарий расширился: появился объект window, функции работы с таймером и пользовательские функции.
Объект window
Объект верхнего уровня в иерархии
JavaScript.
Обладает свойствами, обработчи-
ками событий и методами, которые
позволяют обнаруживать события
браузера и реагировать на них.
Событие onFocus сообщает об акти-
визации окна браузера.
Событие onBlur сообщает о потере
фокуса окном.
Функции работы с таймером
Методы объекта window.
setTimeout обеспечивает вызов функ-
ции с заданной задержкой.
setInterval многократно выполняет
функцию с заданными промежутками.
clearInterval отменяет запланирован-
ные периодические вызовы функции.
Оптимизированные пользова-тельские функцииПользовательские функции позволяют создавать интерактивные веб-страницы, соответствующие современным стан-дартам.
Старайтесь по возможности объединять и оптимизировать ваши функции, чтобы уменьшить объем программного кода. Чем компактнее код, тем проще его со-провождать и отлаживать.
ГЛА
ВА 7
jQuery и Ajax8
Пожалуйста, передайте данные
Использовать jQuery для всяких фокусов с CSS и DOM довольно весело, но при программировании веб-приложений не-обходимо получать данные с сервера и отображать их на странице. Возможно, вам даже захочется обновлять небольшие фрагменты страницы без полной перезагрузки страницы. Технология Ajax в со-четании с jQuery и JavaScript позволяет решить эту задачу. В этой главе вы узнаете, как в jQuery реализуются обращения Ajax к серверу и что можно сделать с полученной информацией.
Щепотку Ajax, каплю jQuery и семь
чашек сливок. Дорогая, ты уверена, что правильно
записала рецепт?
322 глава 8
данные в реальном времени!
От: Отдел маркетинга MegaCorps
Тема: 42-й Ежегодный марафон Интернетвиля — страница результатов
Привет группе веб-разработчиков,
Наша фирма публикует веб-страницу с результатами марафона на кубок Интернет виля. Но наша
страница сильно отстает от реальности, мы обновляем ее только после получения всех результатов.
Пользователи желают моментального обновления информации, как в Twitter и Facebook, и хотят сразу
видеть результаты.Предлагаем вам работу за хорошее вознаграждение. А если сможете обновить нашу страницу
результатов марафона к следующей неделе, можете рассчитывать на места в VIP-ложе в финале.
(Мы упоминали, что в этом году соревнования проходят на Мауи?)
Вот что нам нужно:
1) должна существовать возможность вывода результатов соревнований для мужчин, для женщин
или для всех участников сразу;
2) информация на странице должна обновляться по мере того, как участники пересекают финишную
прямую;
3) обновление результатов должно происходить без перезагрузки страницы;
4) на странице должно быть указано время последнего обновления и частота обновлений.
Пользователи имеют право запускать и останавливать обновления по своему усмотрению.
Внешне страница изменится не сильно, поэтому работу можно начать с прошлогодней версии.
Гонка для нас очень важна, и мы с нетерпением ждем, что у вас получится!
--Диона Хаузни, руководитель отдела маркетинга Фирма MegaCorp Ежегодные
соревнования
В этом году марафон проходит на Мауи,
заказывайте билеты заблаговременно!
ЕЕ
с рсор
Áåãîì ê ñîâðåìåííûì òåõíîëîãèÿì
Похоже, наша
группа уже
представляет
себя на Гавайях...
Но сначала нуж-
но выполнить
работу!
Чуваки, Мауи! Вот здорово,мы попадем на VIP-вечеринку!
дальше � 323
jquery и ajax
Эти вкладки соз-даются модулем расширения (по-дождите немного, все объясним)...
Результат вызова функции getTime.
После заверше-ния марафона информация жестко кодиру-ется в странице.
Íàñòðîéêà ìîäóëÿ ðàñøèðåíèÿ
Модули расширения совершенствуют функциональ-ность базовой библиотеки jQuery или упрощают выполнение некоторых операций. В приведенном примере модуль idTabs в сочетании с CSS преобра-зует элемент ul во вкладки, активизируемые щелч-ками, и сообщает ссылкам a в элементах li, какие элементы div должны отображаться. Этот модуль расширения предоставляет очень удобную навига-ционную структуру для страниц, обеспечивая визу-альное разделение разных видов информации при использовании общей области вывода.
Ïðîøëîãîäíÿÿ ñòðàíèöà
Давайте поближе познакомимся с прошлогодней страницей. Посмотрим, как она выглядела и как была устроена ее разметка. Все это поможет нам лучше понять, чего же от нас хочет заказчик.
Пока не обра-щайте внима-ния на модули расширения.
Они предоставляют дополнительную функциональность для стандартной биб-лиотеки jQuery. Мы остановимся на этой теме в главе 10, а пока просто посмотрим, что может сделать этот модуль для уско-рения работы над проектом…
Р А СС Л А Б Ь Т Е С Ь
324 глава 8
готовый код
Прежде чем двигаться дальше, мы также просмотрим прошло-годние файлы. Код и разметка находятся в файле last_year.zip (вместе с другими файлами этой главы, которые можно загру-зить по адресу http://thinkjquery.com/chapter08 ). Ниже приведены фрагменты трех основных файлов, которые нам понадобятся: my_style.css, index.html и my_scripts.js.
#main ul a:hover {
color:#FFF;
background:#111;
}
#main ul a.selected {
margin-bottom:0;
color:#000;
background:snow;
border-bottom:1px solid snow;
cursor:default;
}
#main div {
padding:10px 10px 8px 10px;
*padding-top:3px;
*margin-top:-15px;
clear:left;
background:snow;
height: 300px ;
}
#main div a { color:#000; font-weight:bold;
}
body{
background-color: #000;
color: white;
}
/* Стиль вкладок */
#main {
color:#111;
width:500px;
margin:8px auto;
}
#main > li, #main > ul > li
{ list-style:none; float:left; }
#main ul a {
display:block;
padding:6px 10px;
text-decoration:none!important;
margin:1px 1px 1px 0;
color:#FFF;
background:#444;
}
my_style.css
Комментарий CSS
Весь дальнейший код CSS предна-значен для создания вкладок.
Готово к употреблению
дальше � 325
jquery и ajax
<div id="main">
<ul class="idTabs">
<li><a href="#about">About the Race</a></li>
<li><a href="#finishers">All Finishers</a></li>
</ul>
<div id="about">
<h4>About the race</h4>This race Bit to Byte Campaign!
</div>
<div id="finishers">
<h4>All Finishers</h4>
<ul id="finishers_all">
<li>Name: Bob Hope. Time: 25:30</li>
<li>Name: John Smith. Time: 25:31</li>
<li>Name: Jane Smith. Time: 25:44</li>
...
</ul>
</div>
...
<script src="scripts/jquery-1.6.2.min.js"></script>
<script src="scripts/my_scripts.js"></script>
<script src="scripts/jquery.idTabs.min.js"></script>
$(document).ready(function(){
getTime();
function getTime(){
var a_p = "";
var d = new Date();
var curr_hour = d.getHours();
(curr_hour < 12) ? a_p = "AM" : a_p = "PM";
(curr_hour == 0) ? curr_hour = 12 : curr_hour = curr_hour;
(curr_hour > 12) ? curr_hour = curr_hour - 12 : curr_hour = curr_hour;
var curr_min = d.getMinutes().toString();
var curr_sec = d.getSeconds().toString();
if (curr_min.length == 1) { curr_min = "0" + curr_min; }
if (curr_sec.length == 1) { curr_sec = "0' + curr_sec; }
$('#updatedTime').html(curr_hour + ":" + curr_min + ":" + curr_sec + " " + a_p );
}
});
my_scripts.js
Новый экземпляр объекта JavaScript Date
Методы объекта Date
Тернарный оператор JavaScript (подробности чуть позже)
index.html
Часть информации о прошло-
годних участниках закодирована
в странице. Тем, кто занимался
обновлением, не позавидуешь...
Как обычно, включаем файлы JavaScript. Этот же механизм используется для подключения модулей расширения.
Создание ссылок, которые будут преобразованы во вкладки модулем расширения.
Элементы div для хранения содержимого вкладок
Вызов пользовательской функции getTime
326 глава 8
долой жесткое кодирование результатов
Äàåøü äèíàìèêó!
Заказчик хочет, чтобы страница обновлялась практически в реальном времени, так что от жесткого кодирования результатов в файле HTML придется отказаться. А код JavaScript прежде использовался только для обновления времени на странице! А нам представи-лась идеальная возможность поднять свои навыки jQuery на следующий уровень. jQuery, JavaScript, немного Ajax и XML... И веб-приложения следующего поколения начинают вы-глядеть как динамические (в отличие от статических) настольные приложения, оперативно реагирующие на происходящие события.
Ajax (сокращение от Asynchronous JavaScript and XML, т. е. «Асинхронный JavaScript и XML») — механизм передачи структурированных данных между веб-сервером и браузе-ром, без участия посетителя сайта. При использовании Ajax ваши страницы и приложе-ния запрашивают у веб-сервера только то, что им действительно необходимо — только те части страницы, которые должны измениться, и веб-сервер предоставляет им только эти данные. Это приводит к сокращению трафика, более компактным обновлениям и ускоре-нию перерисовки.
А самое лучшее, что страницы AJax строятся на базе стандартных интернет-технологий, которые вы уже встречали в этой книге или уже знали прежде:
HTML
CSS
JavaScript
The DOM
При использовании Ajax ваши веб-страницы
запрашивают у сервера необходимую инфор-
мацию в тот момент (и там), когда это нужно.
Для использования Ajax необходимо поближе познакомиться с весьма популярным форматом данных XML и с методом jQuery для обработки Ajax-запросов ajax.
дальше � 327
jquery и ajax
Ñòðàíèöà, óæå
çàãðóæåííàÿ â áðàóçåðå
Ñåðâ
åðÑòðàíèöà, óæå
çàãðóæåííàÿ â
áðàóçåðå
Ñåðâ
åð
ÑÒÀÐÛÅ è ÍÎÂÛÅ âåá-òåõíîëîãèè
Несмотря на то что мы уже кое-что знаем о jQuery, работа с данными угрожает затянуть нас в эпоху старых веб-технологий, когда для частичного или полного обновления данных нам приходилось обновлять целую страницу или переходить к другой странице. А вместе со старыми веб-технологиями возвращается и эпоха медлительных сайтов, когда с серве-ра каждый раз приходилось заново запрашивать всю страницу. Какой прок в изучении классных возможностей JavaScript, если работа с данными снова все замедлит?
Çíàêîìüòåñü: Ajax
Ajax позволяет организовать динамический обмен данными с сервером. Используя Ajax и манипуляции с DOM в коде jQuery и JavaScript, можно загружать или обновлять только часть страницы.
Код JavaScript Çàïðîñ Ajax,ïåðåäàííûé ñåðâåðó
1
Код jQuery или JavaScript обра-щается к серверу с запросом Ajax.
Код JavaScriptÎòâåò, ïîëó÷åííûé
îò ñåðâåðà
2
Îáíîâëåíèå ÷àñòè
ñòðàíèöû
Код jQuery или JavaScript получает результат, раз-бирает его и обновляет только часть страницы.
328 глава 8
главное — данные
Ñòðóêòóðà Ajax
Как упоминалось ранее, Ajax — механизм передачи структурированных данных между веб-сервером и браузером без участия посетителя сайта. Но в действительности Ajax — не монолит, а комбинация нескольких разных технологий для построения впечатля-ющих, интерактивных веб-приложений. JavaScript позволяет взаимодействовать со структурой DOM страницы. Асинхронность означает, что передача данных может осу-ществляться в фоновом режиме, без нарушения работы страницы или участия пользо-вателя, взаимодействующего со страницей. А буква «X» в названии относится исключи-тельно к формату данных.
×òî òàêîå Ajax?
Да, можно использовать HTML. Но в области пере-дачи информации XML об-ладает рядом уникальных преимуществ перед своим родственником HTML. Да-вайте разберемся, что это за преимущества.
Но почему нельзя ис-пользовать HTML? Зачем
нужен еще один язык разметки?
XML
XML (eXtensible Markup Language) — спецификация хранения информации, а также описания структуры этой ин-формации. И хотя XML является языком разметки (как и HTML), он не имеет соб-ственных тегов. XML позволяет автору разметки создать любые теги, которые ему потребуются.
Àñèíõðîííûé
JavaScript обращается с запросом к серверу. В это время вы можете взаимодействовать со страницей: вводить данные в формах, даже нажимать кнопки, пока веб-сервер работает где-то на заднем плане. Затем, когда сервер вернет результаты своей работы, ваш код мо-жет обновить только измененную часть стра-ницы. Вам вообще не приходится ждать! Тако-ва сила асинхронных запросов!
JavaScript
JavaScript, как вы уже знаете, — язык сценариев, используемый при разработ-ке веб-приложений, прежде всего для создания функций, встраиваемых или включаемых в документы HTML и взаи-модействующих с DOM.
A J A X
дальше � 329
jquery и ajax
<?xml version="1.0" encoding="utf-8"?>
<books>
<book>
<title>The Hitchhikers Guide to the Galaxy</title>
<author>Douglas Adams</author>
<year>1980</year>
</book>
<book>
<title>The Color of Magic</title>
<author>Terry Pratchett</author>
<year>1983</year>
</book>
<book>
<title>Mort</title>
<author>Terry Pratchett</author>
<year>1987</year>
</book>
<book>
<title>And Another thing...</title>
<author>Eoin Colfer</author>
<year>2009</year>
</book>
</books>
Ôàêòîð «X»
XML — сокращение от слов « eXtensible Markup Language» (т. е. «расширяемый язык разметки»). Это широко распространенный, стандартизированный способ представления данных и текста в форма-те, который может обрабатываться без существенного вмешательства человека. Информация, от-форматированная в XML, может передаваться между разными платформами, приложениями и даже разными языками (как языками программирования, так и естественными). Она также может исполь-зоваться в широком спектре средств разработчика и служебных программ. Данные в формате XML легко создаются и редактируются; все, что для этого необходимо — это простой текстовый редактор и объявление XML в начале файла. А остальное зависит только от вас!
XML íè÷åãî íå ÄÅËÀÅÒ!
Это может прозвучать немного странно, но XML сам по себе практически ничего не делает. Задача XML — структурирование и хранение информации для передачи. По сути, XML является метаязыком для описания языков разметки. Иначе говоря, XML предоставляет механизм описания тегов и струк-турных отношений между ними. Важно понимать, что XML не заменяет HTML, а лишь дополняет его. Во многих веб-приложениях XML используется для форматирования данных для передачи, тог-да как HTML используется для форматирования и отображения данных. Посмотрим, как выглядит файл XML с информацией о книгах.
XML используется для фор-
матирования данных с целью
передачи, тогда как HTML
используется для форматиро-
вания и отображения данных.
Объявление XML должно присутствовать в каж-дом документе. В нем определяется версия XML, используемая в документе.
Другие теги используются для хранения данных.
Закрытие корневого узла (или тега)
Потомки корневого узла (открывающие и закрывающие теги).В данном случае опи-сываются книги.
Корневой узел (или тег)
books.xml
330 глава 8
не бывает глупых вопросов
В: Главное достоинство XML —- воз-можность создания своих тегов?
О: Точно! Очень удобно определять эле-менты и структуры, соответствующие по-требностям вашей задачи. Что еще лучше, формат XML стандартизирован, поэтому очень многие люди умеют работать с ним.
В: А не проще ли определить собствен-ный формат данных?
О: На первый взгляд кажется, что проще, но закрытые форматы данных (которые вы создаете для себя) создают проблемы. Если их не документировать, пользовате-ли забудут, как они работают. А если что-нибудь изменится, вам придется проследить за обновлением всего: клиента, сервера, базы данных, документации… Это весьма хлопотно.
В: И что, XML действительно так широ-ко используется?
О: Благодаря гибкости при создании лю-бых необходимых структур данных, язык XML стал основой многих языков разметки в Web. Сейчас существует более 150 разных типов языков, основанных на XML: RSS (RDF Site Summary или Real Simple Syndication)
для создания каналов новостей или аудио/видеоматериалов; KML (Keyhole Markup Language) для географической информации, используемой в Google Earth; OOXML (Office Open XML) для файлов текстовых процессо-ров, предложенный Microsoft; SVG (Scalable Vector Graphics) для описаний двумерных векторных изображений; SOAP (Simple Object Access Protocol) для определений методов обмена информацией с веб-службами... Ко-личество применений XML огромно!
В: Ладно, я понимаю, почему XML стоит использовать, но разве он не превра-щается в «закрытый формат данных», когда мы начинаем объявлять имена элементов?
О: Нет, не превращается. Именно в этом и заключается изящество XML: он гибок. Сервер и клиент должны работать с оди-наковыми именами элементов, но это со-ответствие часто может быть согласовано на стадии выполнения.
В: А разве не все веб-страницы асин-хронны? Скажем, браузер загружает графику, когда я уже просматриваю страницу...
О: Браузеры асинхронны, а стандартные веб-страницы — нет. Когда веб-странице требуется информация от программы на
стороне сервера, обработка приостанав-ливается, пока сервер не ответит... если только страница не выдаст асинхронный запрос. А для решения этой задачи как раз и предназначается Ajax.
В: Как определить, когда стоит использо-вать Ajax и асинхронные запросы?
О: Руководствуйтесь простым правилом: если вы хотите, чтобы какие-то действия выполнялись, когда пользователь продол-жает работать, вам нужен асинхронный запрос. Но если для продолжения работы пользователю необходима информация или ответ от вашего приложения, пускай подождет. В таких ситуациях используют синхронные запросы.
В: Разве для взаимодействия с XML не нужно использовать XHTML?
О: XHTML — это и есть XML. Язык XHTML не так близок к HTML, как счита-ется. У XHTML более жесткие требования к парсингу кода, он происходит из того же семейства, что и XML. Но это не означает, что он может взаимодействовать с XML лучше, чем HTML. В разметке, приведенной в книге, используется HTML5, который будет включать в себя XHTML5 после публикации спецификаций.
Уговорили, я уже хочу использовать Ajax. Но ведь начинать нужно с про-работки структуры, верно? Так было
всегда... Вы правы.
Давайте разберемся со струк-турой, чтобы мы могли пе-рейти к включению поддерж-ки Ajax в наши страницы…
частоЗадаваемые
вопросы
дальше � 331
jquery и ajax
Сложите из магнитов код создания двух новых вкладок, на которых отображается инфор-
мация о результатах участников: мужчин (идентификатор male) и женщин (идентификатор
female). Вкладку About можно убрать, но вкладка All Finishers должна остаться. В каждом
разделе создайте пустой элемент ul для информации об участниках. Также удалите все
существующее содержимое из элемента ul finishers_all.
<body>
<header>
<h2>________________________</h2>
</header>
<div id="main">
<ul class="idTabs">
<li><a href="_____________">Male Finishers</a></li>
<li><a href="#female">____________________</a></li>
<li><a href="#all">All Finishers</a></li>
</ul>
<div id="male">
<h4>Male Finishers</h4>
<ul id="______________________"></ul>
</div>
<div __________________________>
<h4>Female Finishers</h4>
<ul id="finishers_f"></ul>
</div>
<div _________________________>
<h4>All Finishers</h4>
<ul id=______________________></ul>
</div>
</div>
<footer>
<h4>Congratulations to all our finishers!</h4>
<br>Last Updated: <div id=______________________></div>
</footer>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script src=______________________________></script>
<script src="scripts/jquery.idTabs.min.js"></script>
</body>
index.html
2011 Race Finishers!
Female Finishers
finishers_m
id="all"
"finishers_all"
"updatedTime"
id="female"
#male
"scripts/my_scripts.js"
Развлечения с магнитами
332 глава 8
решение упражнения
<body>
<header>
<h2>________________________</h2>
</header>
<div id="main">
<ul class="idTabs">
<li><a href="_________">Male Finishers</a></li>
<li><a href="#female">____________________</a></li>
<li><a href="#all">All Finishers</a></li>
</ul>
<div id="male">
<h4>Male Finishers</h4>
<ul id="_______________"></ul>
</div>
<div _______________>
<h4>Female Finishers</h4>
<ul id="finishers_f"></ul>
</div>
<div ____________>
<h4>All Finishers</h4>
<ul id=___________________></ul>
</div>
</div>
<footer>
<h4>Congratulations to all our finishers!</h4>
<br>Last Updated: <div id=________________></div>
</footer>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script src=__________________________></script>
<script src="scripts/jquery.idTabs.min.js"></script>
</body>
index.html
Теперь на странице должны появиться две новых вкладки, для мужчин и для женщин.
>
>________________________</
r>
2011 Race Finishers!
____________________</
Finishers</a></li>
____________________Female Finishers
_______________">finishers_m
____________>
h4>All Finishe
id="all"
___________________><"finishers_all"
our finishers!</h
________________><"updatedTime"
v>
_______________>
<h4>Female Finishe
id="female"
s >
"_________"
"#female">
#male
Наш список победителей
Включение модуля рас-ширения jQuery необхо-димо для соз-дания вкладок.
p jq y j
__________________________><
"scripts/jquery.idTabs.min.j
"scripts/my_scripts.js"
Развлечения с магнитами. Решение
дальше � 333
jquery и ajax
Хорошая работа!
Страница постепенно принимает нуж-ный вид. Теперь давайте посмотрим, как получить данные с сервера, чтобы заполнить каждую вкладку актуальной информацией.
Включите в файл index.html код, созданный нами в упражнении с магнитами, и откройте страницу в своем любимом браузере.
Отлично, с этим моду-лем расширения работа идет как по маслу! Я уже слышу
шум прибоя...
Тест-драйв
334 глава 8
метод GET
А пока включите в файл my_scripts.js следующий код (только строки, выделенные жирным шрифтом).
$(document).ready(function(){
$.ajax({
url: "finishers.xml",
cache: false,
dataType: "xml",
success: function(xml){
}
});
getTime();
function getTime(){
var a_p = "";
var d = new Date();
my_scripts.js
$.ajax({
url: "my_page.html"
success: function(data){
}
});
Сокращение jQueryМетод jQuery ajax
URL-адрес данных, запрашиваемых через Ajax
Эта функция выполняется в том случае, если метод ajax был выполнен успешно. Вскоре мы напишем код этой функции.
Данные, возвраща-емые в результате вызова ajax
Полный список всех параметров метода приведен на сайте до-кументации jQuery по адресу http://api.jquery.com/jQuery.ajax/. Также в jQuery существуют вспомогательные методы для рабо-ты с вызовами Ajax. Вскоре мы вернемся к ним, честное слово.
Загружаем файл finishers.xml средствами Ajax.
Параметр обеспечивает ло-кальное кэширование резуль-татов, снижающее количе-ство обращений к серверу.
Тип данных, которые мы рассчитываем получить от сервера.
Ïîëó÷åíèå äàííûõ ìåòîäîì ajax
Нужны данные? jQuery и Ajax их вам с удовольствием предоставят. Метод jQuery ajax возвращает объект (еще не забыли главу 6?) с данными о конкретной опера-ции, которую вы пытаетесь выполнить. Метод ajax может получать много раз-ных параметров; в частности, с его помощью можно отправить данные серверу (POST) или же запросить их с сервера (GET).
дальше � 335
jquery и ajax
Включите в файл my_scripts.js код с предыдущей страницы. Затем загрузите файл с дан-ными XML для этой главы по адресу http://thinkjquery.com/chapter08/step2/finishers.xml и сохраните его в одном каталоге с файлом index.html. Когда это будет сделано, откройте файл index.html в браузере и перейдите на вкладку «Network» (в средствах разработчика в Google Chrome) или на вкладку «Net» (в Firebug для Firefox). Ваш файл XML должен быть здесь вместе с остальными файлами страницы.
Все верно. Теперь, мы знаем, что файл XML загружается, нужно выбрать нужный текст и отобразить его на экране. Нам следует перебрать данные всех участников марафона, чтобы вклю-чить их в нужный список на странице. И действительно, вызовы ajax полезно включить в функции, чтобы их было удобно вызывать в случае надобности.
Вызовы ajax подчиняются политике единого домена!
Политика единого домена — концепция безопасности для JavaScript и других сценарных языков на стороне клиента. Она позволяет сценариям, выполняемым на странице, обращаться к ресурсам (таким как свойства и методы элементов) на том же сервере. Обращения к элементам страниц других серверов блокируются. Проверка не распространяется на директи-вы JavaScript include, но наш файл XML ей подвержен. Это означает, что он должен находиться на одном сервере с загружающей его страницей.
Какая мне польза от XML в сред-ствах разработчика? Как увидеть
данные на экране там, где они мне нужны? И разве не нужно включить
в функцию вызов вида $.ajax?
Тест-драйв
Будьте осторожны!
336 глава 8
методы find и each
Ðàçáîð äàííûõ XML
Мы должны как-то извлечь данные каждого участника из файла XML и отобразить их на экране. К счастью, в jQuery имеется метод find, который ищет элементы по заданному критерию. Метод find перебирает потомков элементов в структу-рированном, иерархическом наборе данных (таком как дерево DOM или доку-мент XML) и строит новый массив с подходящими элементами. Методы find и children похожи (метод children рассматривался в главе 4, когда мы строили вегетарианское меню), однако children переходит только на один уровень вниз по дереву DOM, а нам, возможно, потребуется спуститься глубже.
Сочетание методов find и each позво-
ляет найти группу элементов по неко-
торому условию и в цикле обработать
каждый найденный элемент.
Как вы думаете, с какими компонентами доку-мента XML необходимо взаимодействовать для отображения результатов участников на экране?
$("li").find("ul").css('background-color', 'blue');
Здесь может быть любой селектор.
Здесь может быть любой другой метод jQuery: события, операции с текстом, опера-ции со стилями и т. д.
Здесь может быть лю-бой селектор или группа элементов jQuery.
li lili
lili
lilili li
li li
ul
ul
ul
ul
$("li").find("ul")
Команда находит все элементы ul,
содержащиеся в элементах li, и за-
дает синий цвет фона.
lili
ul
li
Мозговой
штурм
дальше � 337
jquery и ajax
Расставьте магниты так, чтобы у вас получилась функция getXMLRacers, которая вызывает
метод ajax и загружает файл finishers.xml. После успешной загрузки функция стирает все те-
кущее содержимое списков, после чего находит всех участников в файде XML, определяет пол
каждого участника, присоединяет его к соответствующему списку и в любом случае включает
участника в список finishers_all. Затем вызов функции getTime обновляет текущее время
на странице.
function _____________
$.ajax({
url: _________________,
cache: false,
dataType: "xml",
_________ function(xml){
$(_______________).empty();
$('#finishers_f')__________;
$('#finishers_all').empty();
$(xml).find________________(function() {
var info = '<li>Name: ' + $(this).find________________ + ' ' + $(this).find("lname").text() + '. Time: ' + ____________________.text() + '</li>';
if( $(this).find("gender").text() == "m" ){
$('#finishers_m').append_______
}else if ( $(this).find("gender").text() == "f" ){
__________________.append(info);
}else{ }
__________________.append(info);
});
___________
}
});
}
"finishers.xml"
success:
getXMLRacers(){
.empty()
getTime();
(info)
("runner").each
("fname").text()
$('#finishers_f')
$('#finishers_all')
'#finishers_m'
$(this).find("time")
my_scripts.js
Развлечения с магнитами
338 глава 8
решение упражнения
Используя find и each, мы перебираем файл finishers.xml, проверяем пол каждого участника,
а затем размещаем его данные на соответствующей вкладке веб-приложения.
В этом примере строка, начинающаяся с «var info = ...», оказалась слишком длинной, поэтому мы разбили ее надвое. Вам в своем коде делать это необязательно.
function _____________
$.ajax({
url: _________________,
cache: false,
dataType: "xml",
_________ function(xml){
$(_______________).empty();
$('#finishers_f')__________;
$('#finishers_all').empty();
$(xml).find________________(function() {
var info = '<li>Name: ' + $(this).find________________ + ' ' + $(this).find("lname").text() + '. Time: ' + ____________________.text() + '</li>';
if( $(this).find("gender").text() == "m" ){
$('#finishers_m').append_______
}else if ( $(this).find("gender").text() == "f" ){
__________________.append(info);
}else{ }
__________________.append(info);
});
___________
}
});
}
({
_________________,
e: false,
"finishers.xml"
yp
_________ f
$(
________success:
_____________
jax({
getXMLRacers(){
)__________;
l').empty();
__________.empty()
___________
}
getTime();
d_______
ender") te
(info)
_
d________________(f
= '<li>Name: ' +
("runner").each
d________________ +text() + '<
________________("fname").text()
( $( )
__________________
else{ }
$('#finishers_f')
__________________.a$('#finishers_all')
(
_______________)
'#fi i h f')
__
_
)
'#finishers_m'
+ $(this).find______________
") text() == "m" ){
+ d________.t
( fname_$(this).find("time")
my_scripts.js
Очистка всех элемен-
тов ul для заполнения
обновленными данными
Перебор всех элементов runner в файле XML
Проверка пола каждого участника для включения в со-ответствующий список
Кроме того, все
участники включаются
в список finishers_all.Вызов функции getTime для включения в страницу обновленного времени по-следнего вызова функции getXMLRacers
Развлечения с магнитами. Решение
дальше � 339
jquery и ajax
Включите в файл my_scripts.js функцию getXMLRacers. Также замените вызов функ-ции getTime (в секции document.ready) вызовом функции getXMLRacers. Функция getTime теперь вызывается в нашей новой функции. Проследите за тем, чтобы код вы-полнялся через веб-сервер. Так что URL-адрес, например, должен начинаться с префик-са http://, а не file://. Также убедитесь в том, что файл XML находится на одном сервере с файлом HTML; в противном случае у вас возникнут проблемы с нарушением политики единого домена.
Да, должна.
К счастью, в предыдущих главах вы уже видели, как за-планировать регулярное выполнение какой-либо опе-рации на странице. Давайте еще посмотрим, как это делается и какие варианты возможны на этот раз…
Потрясающе, у меня есть функция, которую можно вызвать для получения данных XML. Разве она не должна вы-
зываться многократно, чтобы обновлять страницу автоматически?
Тест-драйв
340 глава 8
всему свое время
Ïëàíèðîâàíèå ñîáûòèé
Как было показано в предыдущей главе, JavaScript и jQuery поддерживают методы для вызова функ-ций с течением времени. У объекта JavaScript window есть четыре метода для работы с таймером: setTimeout, clearTimeout, setInterval и clearInterval. jQuery поддерживает метод delay, но этот метод предназначен для создания эффектов и не поддерживает возможности планирования или повторения действий. Значит, этот метод в нашем случае бесполезен...
Не торопитесь! Это далеко не очевидно. Метод setInterval обычно используется для плани-рования периодических событий на странице, а при зависимости от внешних ресурсов (таких как наш файл данных) он может создать проблемы.
С setInterval следующий вызов произойдет даже, если вызываемая функция еще не завершила работу.
Если вы ожидаете информации с другого сервера или реак-ции пользователя, setInterval может повторно вызвать функцию до получения результатов первого вызова. Порядок возвращения результатов необязательно соответствует порядку вызова функций.
setTimeout(myFunction, 4000); slideDown().delay(5000).slideUp();setInterval(repeatMe, 1000);
setTimeout setInterval delay
Ìåòîäû JavaScript Ìåòîä delay jQuery
Я определяю вре-мя, по истечении которого должна
выполняться функ-ция.
Я приказываю функции выпол-няться через за-
данный промежуток времени.
Я добавляю пау-зу между эффек-тами, объединен-ными в цепочку.
А разве нет? Нужно использовать setInterval, как и в прошлый раз.
Правильно?
Функция, вы-зываемая по истечении тайм-аута
Задержка таймера (в милли-секундах)
Интервал между вызо-вами (в мил-лисекундах)
Функция, вы-зываемая после исте-чения каждого интервала
Выполнение таких цепо-чек в jQuery называется «очередью эффектов».
В данном при-мере метод delay вставляет 5-се-кундную задержку между эффектами slideUp и slideDown.
Будьте осторожны!
дальше � 341
jquery и ajax
Ñàìîàêòèâèçèðóåìûå ôóíêöèè
Самоактивизируемая функция вызывает саму себя в ходе своего нормального выполнения. Такие функции бывают особенно полезны, когда вам нужно дождаться завершения текущей операции, выполняемой функцией, прежде чем выполнять ее снова. Объединяя самоотносимость с вызовом setTimeout, можно запланировать выполнение функции, но перейти к нему только, если преды-дущий вызов функции был успешным. В противном случае управление в точку вызова передано не будет, а следовательно, функция не будет вызвана повторно.
Создайте функцию с именем startAJAXcalls, которая вызывается при загрузке страницы
и которая вызывает функцию getXMLRacers каждые 10 секунд. Определите в начале сценарно-
го файла (в секции $(document).ready) переменную с именем FREQ, которой присваивается
периодичность повторных вызовов getXMLRacers в миллисекундах. Используйте setTimeout
для вызова функции startAJAXcalls с целью ее самоактивизации после завершения
getXMLRacers. Также включите в код вызов функции startAJAXcalls для запуска таймера.
$(document).ready(function(){
function startAJAXcalls(){
}
getXMLRacers();
function getXMLRacers(){
$.ajax({
url: "finishers.xml",
cache: false,
my_scripts.js
Возьми в руку карандаш
342 глава 8
решение упражнения
Функция startAJAXcalls вызывает setTimeout для вызова
getXMLRacers, чтобы получить данные XML и вызвать саму себя. Такой
самовызов гаран тирует, что в следующий раз функция будет вызвана по-
сле завершения предыдущего вызова. Мы предотвращаем накопление
запросов к серверу при низкой пропускной способности сети или если
ответ от сервера не успел вернуться до момента следующего запланиро-
ванного вызова.
В: Во всех книгах об Ajax говорится, что я должен исполь-зовать объект XMLHttpRequest. Это так?
О: Да, но не в jQuery. Веб-программисту не нужно работать с этим объектом напрямую. jQuery делает это за вас при использовании метода ajax. Кроме того, поскольку вызовы Ajax зависят от брау-зера, jQuery вычисляет оптимальный способ выполнения запросов Ajax для каждого посетителя сайта.
В: А что произойдет, если сервер вернет ошибку или не от-ветит? Приложение так и будет ждать?
О: Нет, бесконечное ожидание вам не грозит. Продолжительность тайм-аута задается в одном из параметров вызова ajax. Кроме того, по аналогии с параметром success, позволяющим выполнить функ-цию при успешном завершении, также существуют другие параметры для обработки событий error, complete и т. д.
$(document).ready(function(){
function startAJAXcalls(){
}
getXMLRacers();
function getXMLRacers(){
$.ajax({
url: "finishers.xml",
cache: false,
my_scripts.js
var FREQ = 10000;
setTimeout( function() {getXMLRacers();startAJAXcalls();
},FREQ
);
Функция getXMLRacers мно-гократно вызыва-ется из setTimeout.
Функция будет по-вторно выполнена через 10 секунд.
Значение пере-менной FREQ передается в параметре.
Вызов функции
getXMLRacers обе-
спечивает наличие
данных при загрузке
страницы.
Переменной FREQ присваивается значение 10000 (параметр функ-ции setTimeout задается в милли-секундах).
Так как мы ожи-даем завершения последнего вызова нашей функции, ис-пользуется функ-ция setTimeout.
Запуск только
что созданной функции на-чинает цикл периодических вызовов.
startAJAXcalls();
Возьми в руку карандаш Решение
частоЗадаваемые
вопросы
дальше � 343
jquery и ajax
Обновите файл my_scripts.js только что написанным кодом. Не забудьте включить вы-зов новой функции сразу же после вызова функции getXMLRacers в конце сценария.Откройте страницу в браузере, воспользуйтесь средством «Network» Google Chrome или «Net» в Firebug для Firefox и убедитесь в том, что файл загружается каждые 10 секунд. По-сле проверки измените файл XML в своем любимом текстовом редакторе (используйте приведенные ниже данные) и убедитесь в том, что данные нового участника появились на странице... (Не забудьте сохранить файл XML после обновления!)
<runner>
<fname>Justin</fname>
<lname>Jones</lname>
<gender>m</gender>
<time>29:14</time>
</runner>
Включите данные это-го участника в файл XML, сохраните его. Убедитесь в том, что данные будут автоматиче-ски загружены на страницу.
Ого, все лучше и лучше! Но нет ли более простого
способа вывода обновленного времени на странице?
Тест-драйв
344 глава 8
кто не хочет большего?
Ñåðâåð íàì ïîìîæåò
Как вы уже видели, HTML хорошо подходит для отображения информации на странице, а XML — для форматирования передаваемых данных. А если вы хотите, чтобы страница что-то делала, например определяла текущее время или читала информацию из базы дан-ных? Конечно, можно выйти из положения при помощи jQuery и JavaScript, но почему бы не воспользоваться технологией, предназначенной специально для таких задач?
Стоп! Если вы не выполнили ин-струкции из Приложения II по уста-новке PHP и MySQL, то следующая страница работать не будет. Для нее необходима рабочая поддержка PHP.
Сделайте это, прежде чем читать дальше.
Ñåðâåðíûå ÿçûêè ïðèõîäÿò íà ïîìîùü!
Существует много разных серверных языков (например, JSP, ASP и Cold Fusion), но наше внимание будет сосредоточено на одном из них: PHP.
PHP (сокращение от PHP: Hypertext Processor; да, вот такое рекурсивное сокращение — не спрашивайте нас, почему!) — бесплатный серверный язык сценариев общего назначения, используемый для построения динамических веб-страниц. Файлы, содержащие код PHP, выполняются на сервере; сгенерированный код HTML передается браузеру для отображе-ния. Технология PHP более подробно описана в следующей главе, а пока давайте посмо-трим, как она поможет нам с реализацией «обновляемого времени».
PHP используется
для динамического
генерирования раз-
метки HTML, кото-
рая затем отобража-
ется в браузере.
.php
.php
.php
PHP
Ñåðâ
åð
Áðàóçåð
дальше � 345
jquery и ajax
Êîòîðûé ÷àñ?
Ладно, признаемся: в JavaScript есть готовая функция для получения времени. Но ис-пользовать такую большую, сложную функцию для такой простой задачи... К счастью, PHP предоставляет очень простой способ получения времени с использованием функ-ции date. Как и функции, которые мы создавали ранее, эта функция получает несколь-ко параметров и возвращает дату в формате, описанном переданными параметрами. Главный параметр определяет, как должна отображаться дата. Давайте присмотримся повнимательнее:
date (string $format [, int $timestamp = time() ]);
За полным списком параметров функции date обращайтесь по адресу http://php.net/manual/en/function.date.php.
<?php
date_default_timezone_set('America/Los_Angeles');
echo date("F j, Y, g:i:s a");
?>
Создайте новый файл в той же папке, в которой находится файл index.html, присвойте ему имя time.php. Включите в файл time.php следующий фрагмент:
time.php
Здесь задается часовой пояс для функции date, чтобы функция вернула правильное время для местонахождения пользователя.Команда echo записы-
вает в страницу за-
данную информацию.
Вызов функции date с этими параметрами возвращает дату в том же формате, что и функция JavaScript.
Открывающий тег PHP сообщает серверу, что далее следует код PHP.
Закрывающий тег PHP
В квадратных скобках [ и ] указаны необязательные параметры.Вызываем функцию PHP date.
Параметр с описанием формата,
в котором должна возвращаться
дата. Представляет собой строку.Команды в PHP завер-шаются знаком «;».
PHP тоже использу-ет знак $, но только для переменных.
Задание!
Компоненты формата даты: F — полное название месяца j — день без начальных нулей Y — год из 4 цифр g — часы в 12-часовом формате i — минуты с начальными нулями s — секунды с начальными нулями a — am или pm в нижнем регистре
346 глава 8
тест-драйв
Сохраните файл time.php, откройте его в браузере и убедитесь в правильности форма-та даты. Код PHP должен выполняться через веб-сервер, поэтому URL-адрес должен начинаться с префикса http://, а не file://. Также убедитесь в том, что URL-адрес ука-зывает на сервер, на котором вы занимаетесь разработкой кода.
Да, отправляться на Гавайи еще рано. Еще нужно кое-что сделать.
Вывести на странице информацию о том, когда произошло последнее обновление.
1
Вывести частоту обновлений.2
Предоставить пользователям возможность прекращать и снова запускать обновление на их усмотрение.
3
Небольшой фрагмент кода PHP — и время отображается на экране. Гораздо проще, чем при использовании JavaScript!
Начнем с первого и второго пунктов списка. Мы будем рассматривать их вместе, потому что они связаны друг с другом.
Мне уже не терпится обзавестись брон-зовым загаром. С PHP задача обновления
времени решается проще простого, но ведь у нас остались и другие требования?
Тест-драйв
дальше � 347
jquery и ajax
<footer>
<h4>Congratulations to all our finishers!</h4>
<br><br>
Last Updated: <div id="updatedTime"></div>
</footer>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script src="scripts/my_scripts.js"></script>
index.html
function
"Page refreshes every " + FREQ/1000 + " second(s).");
}
.
.
.
.
function
$( ).load( );
}
Добавьте тег <span> с идентификатором freq в нижний блок страницы index.html. Он ну-
жен для вывода результата новой функции showFrequency, сообщающей частоту обнов-
ления страницы. Также создайте другую функцию с именем getTimeAjax, которая загру-
жает файл time.php с использованием метода load — вспомогательного метода jQuery
для работы с Ajax. Этот метод получает в параметре URL-адрес и автоматически выводит
результат в области div с идентификатором updatedTime. Наконец, замените вызов
функции getTime в getXMLRacers вызовом новой функции getTimeAjax.
my_scripts.js
Возьми в руку карандаш
348 глава 8
решение упражнения
Итак, мы добавили тег <span> с идентификатором freq в нижний блок страницы
index.html; в нем будет отображаться частота обновления страницы. Также была соз-
дана новая функция getTimeAjax, которая загружает файл time.php с использова-
нием вспомогательного метода Ajax load, а потом записывает результат в область
updatedTime. Функция getXMLRacers также была изменена, теперь вместо функции
JavaScript getTime в ней используется функция getTimeAjax.
<footer>
<h4>Congratulations to all our finishers!</h4>
<br><br>
Last Updated: <div id="updatedTime"></div>
</footer>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script src="scripts/my_scripts.js"></script>
index.html
function
"Page refreshes every " + FREQ/1000 + " second(s).");
}
.
.
.
.
function
$( ).load( );
}
my_scripts.js
<span id="freq"></span>
showFrequency(){$("#freq").html(
getTimeAjax(){'#updatedTime' "time.php"
Добавляем элемент для вы-вода частоты обновлений.
Создаем две новые функции: для вывода частоты и для получения времени с сервера средствами Ajax.
Загружаем файл
time.php сред-
ствами Ajax.Результат выводится на
экран в элементе updatedTime.
Делим на 1000, чтобы преобразовать милли-секунды в секунды.
Возьми в руку карандаш Решение
дальше � 349
jquery и ajax
Это не так просто.
Нужно изменить код функции так, чтобы она выполнялась только при соблюдении некоторых условий.
Но как остановить работу функции, которая вызывает
сама себя?
Вывести на странице информацию о том, когда произошло последнее обновление.
1
Вывести частоту обновлений.2
Предоставить пользователям возможность прекращать и снова запускать обновление на их усмотрение.
3
Какие конструкции из рассмотрен-ных нами ранее проверяли выпол-нение условий?
Включите только что написанный код в файл my_scripts.js. Также не забудьте включить но-вый элемент span в файл index.html и заменить вызов функции getTime на getTimeAjax.
Тест-драйв
Мозговой
штурм
350 глава 8
очередная условная проверка
Îòêëþ÷åíèå ïëàíèðîâàíèÿ ñîáûòèé íà ñòðàíèöå
В главах 5 и 7 мы создали функцию, которая использовала setTimeout для постоянного вызова функций, создававших эффект молнии. Это привело к неожиданным последствиям — при потере фокуса страни-цей и последующем возвращении визуальные эффекты начинали гро-моздиться друг на друга.
А так как мы уже определили, что в нашей ситуации нужно дождаться завершения предыдущего вызова, мы не можем переключиться на ис-пользование setInterval для этих вызовов.
Нужно найти другое решение. Может, что-нибудь из того, что мы уже видели? Мы не можем использовать события браузера window.onblur и window.onfocus — не заставлять же пользователя поки-дать страницу для обновления. Но уже в нескольких главах нам встре-чались примеры выполнения кода в условных конструкциях; давайте воспользуемся этой возможностью и на этот раз.
Как вы думаете, какую условную конструкцию сле-дует применить в данной ситуации? (Подсказка: мы уже использовали ее для проверки пола участников в файле XML.)
Еще монстры нужны??
В: А что еще, кроме XML, можно загру-жать в странице средствами Ajax?
О: При использовании jQuery на странице можно загружать много разных видов ин-формации. Как вы уже видели, метод load позволяет загрузить результаты файла PHP прямо в элемент HTML. Также возможна загрузка других файлов HTML, файлов JavaScript, простого текста и объектов JSON (JavaScript Object Notation). Объекты JSON рассматриваются в следующей главе.
В: Какие еще вспомогательные методы для работы с Ajax существуют в jQuery?
О: В jQuery существует пять вспомога-тельных методов для работы с Ajax: get, getJSON, getScript, post и load. Первые четыре вызываются через объект jQuery, но метод load может вызываться для любого элемента, который использует-ся в качестве приемника для возвращаемых данных.
В: Когда следует использовать метод load, а когда ajax?
О: Метод load предназначен для за-грузки конкретного блока данных в кон-кретное место, как в нашей функции getTimeAjax. Метод ajax намного сложнее, он имеет больше параметров и находит более широкое применение. Он мо-жет использоваться для загрузки другой информации, а также для передачи данных на сервер для обработки. Эти возможности будут представлены в следующей главе.
Мозговой
штурм
частоЗадаваемые
вопросы
дальше � 351
jquery и ajax
Создайте глобальную переменную repeat со значением по умолчанию true. Создайте функ-
цию, которая изменяет переменную repeat по щелчку новой кнопки с идентификатором
btnStop. Запишите в элемент span с идентификатором freq код HTML для вывода сообщения
«Updates paused». Создайте кнопку btnStart, которая присваивает глобальной переменной
repeat значение true и вызывает функции startAJAXcalls и setTimeout, когда пере-
менная repeat принимает значение true. Разместите новые кнопки в нижнем блоке страницы.
$(document).ready(function(){
var FREQ = 10000;
function startAJAXcalls(){
setTimeout( function() {
getXMLRacers();
startAJAXcalls();
},
FREQ
);.. $("#btnStop").click(function(){
$("#freq").html( );
});
function(){
startAJAXcalls();
});
<footer>
<h4>Congratulations to all our finishers!</h4>
<br>
<span id="freq"></span> <br><br> index.html
my_scripts.js
Возьми в руку карандаш
352 глава 8
решение упражнения
Когда все сделано, в приложении появляется переменная repeat. От ее со-
стояния зависит, будет ли функция вызывать сама себя для получения файла
XML с обновленной информацией. Значение переменной меняется кнопка-
ми btnStop и btnStart, находящимися в нижнем блоке стра ницы. Эти
кнопки задают текст элемента span с идентификатором freq, чтобы при
включенном или отключенном обновлении выводились разные сообщения.
$(document).ready(function(){
var FREQ = 10000;
function startAJAXcalls(){
setTimeout( function() {
getXMLRacers();
startAJAXcalls();
},
FREQ
);.. $("#btnStop").click(function(){
$("#freq").html( );
});
function(){
startAJAXcalls();
});
<footer>
<h4>Congratulations to all our finishers!</h4>
<br>
<span id="freq"></span> <br><br> index.html
my_scripts.js
var repeat = true;
repeat = false;"Updates paused."
$("#btnStart").click(repeat = true;
showFrequency();
)
if(repeat) {
<button id="btnStop">Stop Page Updates</button><button id="btnStart">Start Page Updates</button>
По умолчанию пере-
менная равна true,
поэтому при загрузке
страницы обновление
включено.
Проверяем переменную repeat.
При щелчке на кнопке btnStop переменной присваивается значе-ние false.
Кнопка btnStart возвраща-
ет переменной значение true.
Также необходимо вызвать
функцию startAJAXcalls для
того, чтобы файл снова за-
гружался.Новые кнопки раз-мещаются в нижнем блоке страницы.
Возьми в руку карандаш Решение
дальше � 353
jquery и ajax
Включите новый код в файлы my_scripts.js и index.html. Загрузите страницу в своем любимом браузере и убедитесь в том, что она по-прежнему работает. Проверьте, что новые кнопки действительно останавливают выдачу запросов Ajax (воспользуйтесь вкладкой «Network» в Google Chrome или вкладкой «Net» в Firebug для Firefox).
Это будет ЛУЧШИЙ выезд нашей группы!
Работает!
Итак, теперь наша страница обнов-ляется в реальном времени (через обновление файла XML), а пользо-ватели имеют возможность запу-скать и останавливать обновление по своему усмотрению.
Тест-драйв
354 глава 8
ваш инструментарий jquery/ajax
Ajax
Комбинация технологий, позволяю-
щая обновить часть веб-страницы
без повторной загрузки всей стра-
ницы.
Использует обращения к служебно-
му серверу, который обрабатыва-
ет данные до того, как вернуть их
приложению.
В jQuery функциональность Ajax
реализуется методом ajax.
Вспомогательные методы
ajax()
В jQuery существует пять вспо-
могательных методов, упрощаю-
щих вызов ajax. Все они по умол-
чанию получают разные наборы
параметров, но в конечном итоге
вызывают метод ajax:
$.get
$.getJSON
$.getScript
$.post
$.load
XMLФормальный, но гибкий язык раз-метки для описания данных и их структур.
Часто используется для хранения информации или для форматирова-ния данных с целью передачи.Используется во многих распро-страненных веб-технологиях: RSS, SOAP/веб-службы, SVG и др.
Âàø èíñòðóìåíòàðèé jQuery/Ajax
Глава 8 осталась позади. Ваш творческий инструментарий расширился: в нем появи-лись навыки работы с PHP, XML и Ajax.
PHPСерверный язык сценариев; позволя-
ет обработать содержимое веб-
страницы на сервере до того, как
передавать ее клиентскому брау-
зеру.
ГЛА
ВА 8
Данные JSON9
Клиент встречается с сервером
Возможность чтения данных из файлов XML безусловно полезна, но иногда этого оказывается недостаточно. Другой, более эффектив-ный формат передачи данных JSON (JavaScript Object Notation) упрощает получение данных со стороны сервера. Кроме того, данные JSON проще генерируются и читаются, чем данные XML. При помощи jQuery, PHP и SQL можно создать базу данных для хранения информации, которая позднее чи-тается с использованием JSON и отображается на экране средствами jQuery. Вот она, истинная мощь веб-приложений!
Цветы? Надеюсь, потом будут и данные. Но это может
стать началом прекрасной дружбы.
356 глава 9
надо было проверить...
От: Отдел маркетинга MegaCorpТема: Re: страница результатов 42-го ежегодного марафона
Привет веб-программистам!
Нам очень понравились изменения, внесенные вами на сайте.
Однако мы столкнулись с проблемой: в нашем офисе никто не знает XML! И мы не понимаем,
как включить данные новых участников в файл для сайта.
Мы пытались, но при малейшей неточности на сайте начинает твориться что-то странное...
Участники не отображаются; поля исчезают со страницы, хотя они и присутствуют в файле
XML. Все это очень странно.
Нам хотелось бы, чтобы для ввода нового участника было достаточно заполнить несколько
полей и нажать кнопку. Вы сможете это сделать?
И так, чтобы возможные ошибки не нарушали нормальной работы сайта...
Знаю, что до вылета на Гавайи осталось всего три дня, но нам хотелось бы, чтобы сайт зара-
ботал до нашего отъезда. Как вы думаете, мы успеем?
--Диона Хаузни Руководитель отдела маркетинга Фирма MegaCorp
Ежегодные соревнования
Отсчет пошел:осталось 3 дня!
ЕЕ
с рсор
 îòäåëå ìàðêåòèíãà MegaCorp íèêòî íå çíàåò XML
дальше � 357
данные json
Îøèáêè â XML
Если файл XML содержит некорректные данные, то чтение и разбор XML перестают работать. Такие ошибки возникают из-за проблем с тегами (если вы забыли закрыть тег или использова-ли неправильный регистр символа в имени тега). Данные тоже могут создать проблемы, если они не были должным образом закодированы для использования в XML.
Куда исчезли все участники?
При открытии файла XML в браузере выводится информа-
ция об обнаруженных ошибках.
Неправильный регистр символов в теге <runner>
Непра-вильный откры-вающий
тег
Снова непра-вильный регистр в теге <runner>Похоже, XML не подойдет. Как орга ни зовать ввод информации об участниках в отделе маркетинга?
Мозговой
штурм
358 глава 9
формы приходят на помощь
Ââîä äàííûõ íà âåá-ñòðàíèöå
Скорее всего, вы уже подумали об использовании формы HTML. На форме можно ввести любые данные и передать их серверу для обработки, а используемые на них разнообразные элементы позво-ляют вводить самые разные виды данных. Формы будут более подробно описаны в главе 10, а пока мы воспользуемся всего двумя простейшими элементами форм: текстовым полем и раскрывающим-ся списком. Возможно, вы уже профессионально разбираетесь в формах, и все же давайте в общих чертах посмотрим, с чем мы имеем дело.
Наверное, проще всего создать новую вкладку с формой для
ввода данных?
<input type="text" name="txtEmail" />
<select name="truthiness">
<option value="1">True</option>
<option value="0">False</option>
</select>
Тег <input> со-
общает фор-ме, что этот
элемент будет
поставлять информацию.
Атрибут type указывает браузеру, как следует ото-бражать этот элемент.
Имя элемента передается серверу для обработки.
Закрывающий тег элемента
Тег < select> сооб-
щает браузеру,
что нужно вы-
вести раскрыва-
ющийся список.
Элемент option опреде-
ляет пункт раскрываю-
щегося списка.Значение value выбранного пункта списка отправляется серверу.
Да, такое решение будет работать и легко реали-зуется, так как мы уже умеем добавлять новые вкладки.
А после этого можно будет заняться сохранением/загрузкой этих данных для отображения в списках участников.
дальше � 359
данные json
<ul class="idTabs">
<li><a href="#male">Male Finishers</a></li>
<li><a href="#female">Female Finishers</a></li>
<li><a href="#all">All Finishers</a></li>
<li><a href="#new">Add New Finisher</a></li>
</ul>
<div id="male">
<h4>Male Finishers</h4><ul id="finishers_m"></ul>
</div>
<div id="female">
<h4>Female Finishers</h4><ul id="finishers_f"></ul>
</div>
<div id="all">
<h4>All Finishers</h4> <ul id="finishers_all"></ul>
</div>
<div id="new">
<h4>Add New Finisher</h4>
<form id="addRunner" name="addRunner" action="service.php" method="POST">
First Name: <input type="text" name="txtFirstName" id="txtFirstName" /> <br>
Last Name: <input type="text" name="txtLastName" id="txtLastName" /> <br>
Gender: <select id="ddlGender" name="ddlGender">
<option value="">--Please Select--</option>
<option value="f">Female</option>
<option value="m">Male</option>
</select><br>
Finish Time:
<input type="text" name="txtMinutes" id="txtMinutes" size="10" maxlength="2" />(Minutes)
<input type="text" name="txtSeconds" id="txtSeconds" size="10" maxlength="2" />(Seconds)
<br><br>
<button type="submit" name="btnSave" id="btnSave">Add Runner</button>
<input type="hidden" name="action" value="addRunner" id="action">
</form>
</div>
Включите в файл index.html новую вкладку для вво-да информации об участниках на форме. Также внесите изменения в файл my_style.css, чтобы уве-личить ширину элемента с идентификатором main.
Добавляем новую форму HTML для сбора данных и их передачи серверу.
Скрытое поле HTML. Вскоре мы расскажем о том, как используется это поле.
Добавляем новую вкладку.
Атрибут action сообщает форме, куда следует передать данные для обработки. Атрибут
method определя-ет способ передачи данных сер-веру.
#main {
background:#181818;
color:#111;
padding:15px 20px;
width:600px;
border:1px solid #222;
margin:8px auto;
}
index.html
my_style.css
Готово к употреблению
360 глава 9
тест-драйв
Новая форма Новая форма HTML в браузереHTML в браузере
Откройте файл index.html в браузере. Перейдите на вкладку Add New Finisher, присмотритесь к новой форме и полям, добавленным на страницу.
Итак, теперь у нас есть форма для ввода данных. Как, по вашему мнению, следует организовать хра-нение и выборку данных?
Тест-драйв
Мозговой
штурм
дальше � 361
данные json
<form id="my_form" method="get" action="x.php">
<input type="text" name="a" value="1" />
<input type="text" name="b" value="2" />
</form>
<form id="my_form" method="post" action="x.php">
<input type="text" name="a" value="1" />
<input type="hidden" name="c" value="3" />
</form>
<?php
echo $_GET["a"] ; // Writes out "1"
echo $_GET["b"] ; // Writes out "2"
?>
<?php
echo $_POST["a"] ; // Writes out "1"
echo $_POST["c"] ; // Writes out "3"
?>
×òî äåëàòü ñ äàííûìè
Теперь необходимо отправить серверу данные, введенные на форме, и как-то их сохранить. Для сохра-нения информации в базе данных мы воспользуемся другим языком, PHP. Не волнуйтесь, скоро мы по-говорим о PHP и базах данных, а пока сосредоточимся на том, как передать данные от формы серверу.
Существуют два способа отправки данных серверу с использованием HTTP: GET и POST (они также называются «методами»). Главное различие между GET и POST — конкретный механизм передачи дан-ных. GET присоединяет имена полей формы и их значения в конец URL-адреса в формате пар «ключ/значение». PHP читает эту информацию из ассоциативного массива $_GET[], который передается сер-веру при отправке данных формы. Передаваемые данные следуют после знака ? в URL-адресе.
Метод POST тоже передает данные в ассоциативном массиве, но они кодируются другим способом, и эти данные не видны конечному пользователю в URL-адресе. В ассоциативном массиве $_POST[] хранится вся информация из элементов формы. Таким образом, как и массив $_GET[], он состоит из пар «ключ/значение» элементов формы.
Метод HTTP GET Метод HTTP POST
Отправка данных серверу. Отправка данных серверу.
x.php?a=1&b=2 x.php
Да, форма может отправить информацию...
Но как упоминалось в предыдущей главе при описании преимуществ jQuery и Ajax, отправка или получение данных не требует повторной загрузки всей страницы. Но прежде чем отправлять данные серверу средствами jQuery и Ajax, необходимо подготовить их к отправке.
В этой главе мы будем использовать метод POST.
Но если форма отправляет информацию сама, для чего
jQuery и все остальное?
362 глава 9
серьезная сериализация
Ôîðìàòèðîâàíèå äàííûõ ïåðåä îòïðàâêîé
Прежде чем отправлять информацию серверу (средствами Ajax), необходимо сначала подготовить ее — преобразовать в формат, который может передаваться вызовами Ajax и который будет поня-тен серверу. Для этого данные сериализуются в один объект, чтобы вызов Ajax мог передать их как единое целое. В jQuery существуют два вспомогательных метода сериализации данных: serialize и serializeArray. Первый объединяет весь ввод на форме в одну строку пар «ключ/значение», разделенных амперсандами (&). Второй создает ассоциативный массив пар «ключ/значение»; массив также является одним объектом, но он намного лучше структурирован, чем результат serialize. Мы рассмотрим обе возможности, но при работе с данными марафона будет использо-ваться метод serializeArray.
$("#my_form").serialize(); $("#my_form:input").serializeArray();
Селектор иден-
тификатора формы
Метод serialize Вызов методаserializeArray
Селектор идентификатора формы, за которым следу-ет фильтр элемента HTML input. Селектор должен най-ти только элементы HTML с типом «input».
serialize serializeArray
<form id="my_form">
<input type="text" name="a" value="1" />
<input type="text" name="b" value="2" />
<input type="hidden" name="c" value="3" />
</form>
<form id="my_form">
<input type="text" name="a" value="1" />
<input type="hidden" name="c" value="3" />
</form>
a=1&b=2&c=3
[
{
name: "a",
value: "1"
},
{
name: "c",
value: "3"
}
]
Результат Результат
дальше � 363
данные json
$('_______________').click(function() {
var data = $("#addRunner :input").___________________();
$.post($("#addRunner").attr('action'), __________ , _______________(json){
if (json.status == "fail") {
alert(json._____________);
}
if (json.status == ______________) {
alert(json.message);
clearInputs();
}
}, "json");
});
function ___________________{
$("#addRunner :input").each(function(){
$(this).val('');
});
}
$("#addRunner").______________(function(){
return false;
});
Îòïðàâêà äàííûõ ñåðâåðó
jQuery предоставляет вспомогательный метод post, предназначенный для отправки данных серверу. Метод post получает несколько параметров (в числе которых URL-адрес, по которому отправляется информация), передаваемую информацию и функцию-обработчик, которая выполняется после за-вершения отправки POST.
Создайте слушателя события click для #btnSave, который получает данные формы и сериализует их.
Информация отправляется серверу методом jQuery post. URL-адрес для отправки берется из атрибута
action формы. Создайте функцию clearInputs , стирающую все данные из полей формы, если отправ-
ка была успешной. Необходимо отменить отправку данных формы по умолчанию (возвращая false),
для чего следует использовать слушателя . submit формы с идентификатором addRunner.
$.post(url_to_send, data, function(json){
});URL-адрес, на который отправля-ются данные
Вспомога-
тельный
метод jQuery Передаваемые дан-ные (уже прошед-шие сериализацию)
Данные возвращаются в объекте с именем json. Не обращайте на него внимания, мы займемся им позднее в этой главе.
Выполня-ется эта функция обратного вызова.
my_scripts.js
serializeArray
#btnSave
"success"
clearInputs()
submit
function
data
message
Развлечения с магнитами
364 глава 9
Тест-драйв
решение упражнения
Создайте слушателя события click для #btnSave, который получает данные формы и сериализует их.
Информация отправляется серверу методом jQuery post. URL-адрес для отправки берется из атрибута
action формы. Создайте функцию clearInputs , стирающую все данные из полей формы, если отправ-
ка была успешной. Необходимо отменить отправку данных формы по умолчанию (возвращая false), для
чего следует использовать слушателя . submit формы с идентификатором addRunner.
После внесения последних изменений внешний вид страницы не изменится. Тем не менее включи-те в файл my_scripts.js созданный код. Откройте страницу index.html в браузере, перейдите на вкладку «Network» (Chrome) или «Net» (Firebug); при каждом нажатии кнопки btnSubmit должна происходить отправка POST файлу service.php. Метод POST указывается в разделе Request Method вкладки Headers. Здесь же приводятся данные формы (Form Data). Осталось только найти место для их сохранения…
$('___________').click(function() {
var data = $("#addRunner :input").________________();
$.post($("#addRunner").attr('action'), ________ , ___________(json){
if (json.status == "fail") {
alert(json.___________);
}
if (json.status == ___________) {
alert(json.message);
clearInputs();
}
}, "json");
});
function _______________{
$("#addRunner :input").each(function(){
$(this).val('');
});
}
$("#addRunner").___________(function(){
return false;
});
________________()
n')
________________serializeArray
___________'
var data = $
#btnSave
___________)
age);
"success"
_______________{
dRunner :input").
clearInputs()
___________(submit
___________(jfunction________ ,data
___________)message
my_scripts.js
Получение атрибута action формы, которая должна отправить данные.
Готовим данные всех полей формы к отправ-ке на сервер.
Проверка значения, возвращенного сервером (и заданного в коде PHP), позволяет узнать, успешно ли прошла отправка POST.
Используем фильтр элементов HTML для перебора всех полей input формы и стирания их содержимого.
Отменяем отправку данных формой по умолчанию, чтобы выполнить ее кодом jQuery в событии click кнопки.
Развлечения с магнитами. Решение
дальше � 365
данные json
В MySQL данные
хранятся в табли-
цах базы данных.
Базы данных MySQL делятся на таблицы, содержимое которых состоит из строк и столбцов. Большинство веб-приложений работает с одной или несколькими таблицами одной базы данных, их можно сравнить с книгами, стоящими на од-ной полке.
Сама база данных часто
хранится в файлах на
жестком диске, но это
необязательно.
Сервер баз данных MySQL может обслу-живать несколько баз данных.
В базе данных мо-жет быть несколь-ко таблиц.
Веб-сервер
Сервер баз данных
Серверный компьютер
Клиентский браузер
База данных MySQL
Сервер баз данных выполняет с базой данных операции чтения и записи.
Веб-сервер обрабатыва-ет запросы веб-страниц, выполняет сценарии PHP и возвращает данные в формате HTML. Данные
Веб-сервер
Сервер баз данных
SQL — язык струк-турированных за-просов (Structured Query Language).
Õðàíåíèå èíôîðìàöèè â áàçå äàííûõ MySQL
Реляционные системы управления базами данных (РСУБД) представляют собой высокоуровневые приложения, предназначенные для хранения и ор-ганизации информации об отношениях между различными видами данных.
Существует великое множество разнообразных РСУБД (также часто назы-ваемых серверами баз данных) разного назначения и размера (и разной стоимости). Для наших целей будет использоваться бесплатный сервер баз данных MySQL. Для взаимодействия с сервером баз данных используется язык, понятный сер-веру, — в нашем случае это язык SQL. Сервер баз данных обычно работает в сочетании с веб-сервером (иногда на одном компьютере) над чтением и за-писью данных, а также выдачей готовых веб-страниц.
SQL — язык запросов,
используемый для взаи-
модействия с базой дан-
ных MySQL.
<? php
>?
366 глава 9
запускаем базу данных
create database hfjq_race_info;
CREATE USER 'runner_db_user'@'localhost' IDENTIFIED BY 'runner_db_password';
GRANT SELECT,INSERT,UPDATE,DELETE ON hfjq_race_info.* TO 'runner_db_user'@'localhost';
use hfjq_race_info;
CREATE TABLE runners(
runner_id INT not null AUTO_INCREMENT,
first_name VARCHAR(100) not null,
last_name VARCHAR(100) not null,
gender VARCHAR(1) not null,
finish_time VARCHAR(10),
PRIMARY KEY (runner_id)
);
Ñîçäàíèå áàçû äàííûõ äëÿ èíôîðìàöèè îá ó÷àñòíèêàõ
Стоп! А вы уже установили и настроили MySQL и PHP? Прежде чем продолжать,
обязательно выполните инструкции по установке и настройке PHP и MySQL
из приложения II.Хорошо, проезжайте.
Теперь вы сможете выпол-нить задания этой главы.
Мы уже написали код создания базы данных, та-блиц и пользователей за вас. Запустите MySQL Workbench, откройте новое подключение и вы-полните следующий код SQL:
Создаем базу данных с именем hfjq_race_info.
Создаем пользователя runner_db_user, задаем ему пароль и разреша-ем этому пользователю получать, добавлять, обновлять и удалять данные из базы.
Указываем сценарию, что следующий фраг-мент относится к на-шей новой базе данных.
Создаем таблицу runners, в которой хранится вся необходимая информа-ция об участниках марафона.
Готово к употреблению
дальше � 367
данные json
И где же данные?
Сейчас мы ими займемся.
Только что выполненный нами код SQL только создает базу данных, создает пользователя, предоставляет новому пользователю доступ к базе данных и создает таблицу для хранения информации. Теперь давайте посмотрим, как сохранить в таблице данные.
Запустите MySQL Workbench и откройте подключение к серверу. Вставьте код SQL на па-нель Query и щелкните на значке с молнией, чтобы его выполнить. На панели Output в нижней части окна должны появиться сообщения об успешном выполнении операций.
Тест-драйв
368 глава 9
это здесь, а это вставляем сюда…
Ñòðîåíèå êîìàíäû insert
Основные операции с базой данных — сохранение информации, ее изменение/обновление и последующее извлечение. Вскоре мы займемся извлечением (выборкой) данных, а пока нас прежде всего интересует то, как занести информацию в таблицы базы данных.
Включение данных в таблицы осуществляется командой insert.
insert into [table_name] ( column_name1, column_name2, column_name3)
values ('value1', 'value2', 'value3' );
Список данных, сохраняемых в таблице (должен соответство-
вать списку столбцов). Элементы
списка разделяются запятыми.
Ключевое слово «values» сообщает команде, что список столбцов завершен, а далее следуют соб-ственно данные.
Ключевые сло-ва «insert into» определяют операцию.
Указывает, в какую таблицу заносятся данные.
Разделенный запятыми список столбцов, в кото-рых сохраняются данные
Команда insert сохраняет информацию в одной таблице. Эти команды обычно используются для вставки одиночных записей, но опытные пользо-ватели могут создавать команды insert для встав-ки сразу нескольких записей. Впрочем, в наших примерах будет использоваться только вставка одиночных записей.
В команде рекомендуется перечислить столбцы в порядке вставки данных, хотя это и необязательно. Если столб-цы не указаны, со вставкой данных мо-гут возникнуть проблемы, потому что первое значение автоматически поме-щается в первый столбец, второе — во второй столбец и т. д. Чтобы пользо-ваться сокращенной записью, необхо-димо хорошо знать структуру таблицы данных.
Порядок следования имен столбцов и значений важен!
Порядок перечисления значений должен соответствовать по-рядку столбцов. По нему база
данных определяет, в какой столбец следует поме-стить то или иное значение.
Значения
Данные вставля-ются в таблицу.
Таблица базы данных
В таблицу добавляется новая запись (строка).
Реляционная база данных
Будьте осторожны!
дальше � 369
данные json
insert into runners (first_name, last_name, gender, finish_time)
values ('John','Smith','m','25:31') ;
Напишите команды SQL insert для вставки данных, уже хранящихся в файле XML. Каждая команда должна вставлять одну запись в созданную нами таблицу. Первую команду мы написали за вас.
Упражнение
370 глава 9
решение упражнения
insert into runners (first_name, last_name, gender, finish_time)
values ('John','Smith','m','25:31') ;
insert into runners (first_name, last_name, gender, finish_time) values ('Jacob','Walker','m','25:54') ;
insert into runners (first_name, last_name, gender, finish_time) values ('Mary','Brown','f','26:01') ;
insert into runners (first_name, last_name, gender, finish_time) values ('Jenny','Pierce','f','26:04') ;
insert into runners (first_name, last_name, gender, finish_time) values ('Frank','Jones','m','26:08') ;
insert into runners (first_name, last_name, gender, finish_time) values ('Bob','Hope','m','26:38') ;
insert into runners (first_name, last_name, gender, finish_time) values ('Jane','Smith','f','28:04') ;
insert into runners (first_name, last_name, gender, finish_time) values ('Ryan','Rice','m','28:24') ;
insert into runners (first_name, last_name, gender, finish_time) values ('Justin','Jones','m','29:14') ;
Весь код SQL, необходимый для вставки информации об участниках в таблицы базы данных, написан. Запустите MySQL Workbench и выполните код.
Пора использовать новый язык: PHP.
Не беспокойтесь! Мы ограничимся толь-ко тем, что необходимо для взаимодей-ствия на стороне сервера (включая обще-ние с сервером баз данных).
Хорошо, информация об участниках сохранена в базе данных. Как теперь
извлечь ее для веб-приложения?
дальше � 371
данные json
<? php
>?
Èñïîëüçîâàíèå PHP äëÿ ðàáîòû ñ äàííûìè
PHP — язык программирования, и для его использования необхо-дима соответствующая среда: веб-сервер с поддержкой PHP. Сце-нарии PHP и веб-страницы, использующие сценарии, должны размещаться на веб-сервере (вместо простого запуска сценария из локальной файловой системы).
Браузеры ничего не знают о PHP, а следовательно, не могут выполнять сценарии PHP.
Веб-серверы с поддержкой PHP умеют выполнять сценарии PHP и преобра-зовывать их в веб-страницы HTML, понятные для браузера.
Сценарии PHP должны
выполняться на веб-сервере,
иначе они работать не будут.
В отличие от страниц HTML,
которые можно открыть в
браузере локально, сценарии PHP
всегда должны «открываться»
по URL-адресу из веб-сервера.
Как быстро определить, была ли веб-страница предоставлена веб-сервером? URL-адреса таких стра-ниц начинаются с префикса «http:». Веб-страницы, открываемые как локальные файлы, всегда начинаются с префикса «file:».
Для браузера этот сценарий PHP представляет собой бес-смысленный набор символов.
Веб-сервер «понимает» код PHP и выполняетсценарий!
Если у вас имеется локаль-но установленный веб-сервер с поддержкой PHP, вы сможете протестиро-вать сценарии PHP прямо на локальном компьютере.
<? php
>?
PHP и MySQL?Я думала, мы здесь изучаем jQuery! Что происходит?
Будет и jQuery, не беспокойтесь.
Но сначала мы должны понять, как файл PHP обрабатывает данные PHST для их сохранения в базе данных. Также необхо-димо упомянуть некоторые важные мо-менты, о которых следует помнить при отправке информации серверу.
372 глава 9
отправка post
Îáðàáîòêà äàííûõ POST íà ñåðâåðå
Мы уже рассмотрели специальный объект $_POST, создаваемый для передачи информации веб-серверу от формы в браузере. Он представляет собой ассоциативный массив со всей отправлен-ной информацией, при этом в качестве ключа используется имя (а не идентификатор!) элемента HTML, а содержимое элемента HTML сохраняется как значение ассоциативного массива. Код PHP на сервере читает объект $_POST и определяет, какая информация была отправлена серверу.
Информация извлекается из массива по ключу, с которым она была отправлена (имя элемента HTML). Так значения становятся доступными в сценарии PHP.
echo $_POST["txtFirstName"];
Значение выводится
на экран.
Имя массива, автоматически соз-даваемого для данных, отправляе-мых файлу PHP методом POST.
Имя элемента HTML, в котором вводились данные на форме.
Ну что еще? Я хочу на пляж!!!
Мы почти добрались до той стадии, когда мы можем извлечь информацию из базы данных и понять, как вывести ее в списках участников. Но сначала нам придется напи-сать еще немного кода PHP для подключе-ния к базе данных…
дальше � 373
данные json
<?php
mysql_connect('127.0.0.1', 'runner_db_user', 'runner_db_password')
OR die( 'Could not connect to database.');
mysql_select_db('hfjq_race_info');
echo "Connected!";
?>
Ïîäêëþ÷åíèå ê áàçå äàííûõ èç êîäà PHP
Помните, как ближе к концу процесса установки PHP мы выбирали библиотеку?
Эта библиотека позволяет PHP взаимодействовать с базой данных MySQL. Мы используем ее для подключения к созданной ранее базе данных, чтобы прочитать из нее информацию об участниках.
Имя сервера, на котором находится база данных MySQL
Пользователь MySQL, с права-ми которого вы подключаетесь к базе данных
Пароль MySQL для пользователя
mysql_connect — функция библиотеки PHP, включенной в ходе установки PHP.
mysql_select_db сообщает PHP, с какой базой данных мы будем работать.
Если подключение к базе данных прошло успешно, сообщение выводится на экран, а если нет, выполнение сценария не до-стигнет этой точки.
Закрывающий тег PHP
Команда die выводит сообщение и заверша-ет сценарий PHP.
Откройте теги PHP.
service.php
374 глава 9
тест-драйв
Вы правы.
Для чтения данных, как и для их вставки, существует специ-альная команда. Давайте посмотрим, как она работает.
Пока что не очень впечатляет. Ну да, мы подключились... но я по-прежнему не вижу данных!
Откройте свой любимый текстовый редактор и добавьте код с предыдущей страницы. Сохраните файл под именем service.php в одном каталоге с файлом index.html этой главы. Откройте файл service.php в браузере и просмотрите результаты запроса к базе данных.
Не забудьте, что код PHP должен выполняться через веб-сервер, поэтому ваш URL-адрес должен начинаться с префикса http://, а не file://.
Тест-драйв
В: MySQL Workbench — единственный способ управления базой данных MySQL?
О: Нет! Существуют другие способы и другие инструменты. PHPMyAdmin — стандартный инструмент на базе веб-технологий для управ-ления базами данных MySQL. Также базой данных можно управлять из окна терминала, вводя данные в командной строке.
В: Какие еще существуют библиотеки PHP?
О: Существует много разных библиотек PHP для разных целей: SSL, работы с электронной почтой (SMTP или IMAP), сжатия данных, про-верки подлинности, подключения к другим базам данных и т. д. Чтобы получить полный список, введите в своей любимой поисковой системе «библиотеки PHP».
частоЗадаваемые
вопросы
дальше � 375
данные json
×òåíèå èç áàçû äàííûõ
Для чтения информации из базы данных используется команда select. Данные возвращаются в виде итогового набора ( resultset) — со-вокупности всех данных, запрашиваемых в запросе select. Команда select также позволяет объединить информацию из нескольких таблиц; таким образом, итоговый набор может содержать данные из двух и более таблиц.
Создайте команду select для получения данных, необходимых для отображения списка
участников на сайте. Из таблицы runners нужно прочитать столбцы first_name, last_name, gender и finish_time. Отсортируйте данные по столбцу finish_time, от низких
значений к высоким. Если понадобится, имена столбцов можно уточнить на с. 366, где мы
создавали таблицу.
select column_name1, column_name2 from table_name order by column_name1 asc
Ключевое слово « order by», за которым следуют име-на одного или нескольких столбцов, обеспечивает сортировку возвращаемых данных в указанном порядке.
Ключевое слово «from» сообщает команде, что список столбцов завер-шен, а за ним следует информация о том, откуда следует взять данные.
Ключевое слово «select» определяет выполняе-мую операцию.
Разделенный запяты-ми список столбцов, из которых извлека-ются данные
Указываем, из какой таблицы извлека-ются данные.
Ключевое слово «asc» в секции «order by» указывает, как сле-дует упорядочить результаты (asc — по возрастанию, desc — по убыванию).
Команда SQL select читает столбцы данных
из одной или нескольких таблиц и возвра-
щает данные в виде итогового набора.
Более подробная инфор-мация о PHP, SQL, базах данных и таблицах при-ведена в книге «Head First PHP & MySQL».
Возьми в руку карандаш
376 глава 9
решение упражнения
Вы только что создали собственную команду SQL для чтения
информации об участниках из базы данных.
SELECT first_name, last_name, gender, finish_time FROM runners order by finish_time ASC
Список столбцов, из кото-рых читаются данные
Выполните команду select в MySQL Workbench. Убедитесь в том, что все данные возвращаются в итоговом наборе.
Потрясающе! Я вижу данные в Workbench... но
ведь они нужны нам на веб-странице?
Да, это верно.
Давайте посмотрим, как вы-вести на странице информа-цию, прочитанную из базы данных.
Способ упоря-дочения данных
Таблица, из которой читаются данные
Возьми в руку карандаш Решение
Тест-драйв
дальше � 377
данные json
Äîñòóï ê äàííûì â êîäå PHP
До настоящего момента мы рассмотрели некоторые простейшие (да и не только простейшие) возможности PHP. Вы уже умеете выводить на экран простые сообщения, умеете подключаться к базе данных и писать команды select для чтения информации. Теперь давайте разберемся, как вывести на экран информацию, прочитанную из базы данных.
Сложите из магнитов код PHP, в котором определяется функция db_connection для
подключения к базе данных. Создайте переменную $query и присвойте ей текст напи-
санной ранее команды select для выборки информации всех участников из базы дан-
ных. Создайте переменную $result, которой присваивается результат вызова функции
db_connection с передачей переменной $query в параметре. Наконец, переберите в
цикле while все строки итогового набора (данные которого хранятся в ассоциативном
массиве) и выведите их на экран.
<?php
$query = "SELECT first_name, last_name, gender, finish_time _____ runners order by ______________ASC ";
$result = ___________________($query);
while ($row = mysql_fetch_array(____________, MYSQL_ASSOC)) {
print_r(_______);
}
_______________db_connection(__________) {
mysql_connect('127.0.0.1', 'runner_db_user', 'runner_db_password')
OR _____ ('Could not connect to database.');
_____________________('hfjq_race_info');
return mysql_query($query);
}
?>
service.php
function
$query
$result finish_time
db_connection
$row
die
FROM
mysql_select_db
Развлечения с магнитами
378 глава 9
частоЗадаваемые
вопросы
решение упражнения
В: Команда select возвращает всю информацию из таблицы? Я могу огра-ничить состав возвращаемых столбцов, а как насчет строк?
О: Да, строки можно ограничить при по-мощи секции where. Мы поговорим об этом в главе 11, а сейчас достаточно сказать, что в секции where передается условие-фильтр, и команда select возвращает строки, ко-торые удовлетворяют указанному условию.
В: Команда может читать данные только из одной таблицы?
О: В запросе можно объединить сколько угодно таблиц, обычно для этого исполь-зуется общий идентификатор или условие where. Объединение большого количества таблиц существенно замедляет запросы к базе данных, поэтому будьте осторожны при использовании этой возможности. Чтобы получить дополнительную информацию по этой теме, почитайте главу 8 книги «Изучаем PHP & MySQL» или главу 2 «Изучаем SQL».
В: Почему база данных находится по адресу 127.0.0.1? Я вижу свой сайт на «localhost». Откуда такие различия?
О: Хороший вопрос. Ответ: различий нет. Адрес 127.0.0.1 и имя «localhost» обознача-ют одно и то же — компьютер/сервер, на ко-тором вы работаете в настоящий момент.
Перед вами небольшой фрагмент кода PHP, который читает информацию из базы дан-
ных, перебирает содержимое полученного массива и выводит его на веб-странице.
<?php
$query = "SELECT first_name, last_name, gender, finish_time _____ runners order by _______________ASC ";
$result = _________________($query);
while ($row = mysql_fetch_array(__________, MYSQL_ASSOC)) {
print_r(_______);
}
___________db_connection(__________) {
mysql_connect('127.0.0.1', 'runner_db_user', 'runner_db_password')
OR _____ ('Could not connect to database.');
_________________('hfjq_race_info');
return mysql_query($query);
}
?> service.php
___________db
mysql_conn
function __________)
1', 'runner
$query
__________,$result
y = "SELECT first________________AS
lt = _
SELECT fi_______________finish_time
_____($______________ e
db_connection
y q
_______);$row
nect
(
_conn
_
die
_____ ruFROM
_____
_________________('
_____
________
_____
mysql_select_db
Развлечения с магнитами. Решение
дальше � 379
данные json
Безусловно!
То, что мы видим перед собой — это выведенное на экран содержимое массивов. Массивы содержат нуж-ные данные, но не в том формате, который нам нужен. К счастью, существует эффективный способ организа-ции данных в формате, идеально подходящем для опре-деления структур данных.
Включите в файл service.php только что написанный код. Откройте страницу в браузере, чтобы увидеть результаты запроса к базе данных. Не забывайте, что код PHP должен вы-полняться через веб-сервер, поэтому URL-адрес должен иметь префикс http://, а не file://.
Результат: все данные успешно выве-дены на экран.
Да, это наши данные, но они какие-то сложные и запутанные. Нельзя
ли их немного «причесать»?
Тест-драйв
380 глава 9
простой способ
{
books:{
book:[
{
title:'The Color of Magic',
author:'Terry Pratchett',
year:1983
},
{
title:'Mort',
author:'Terry Pratchett',
year:1987
},
{
title:'And Another thing...',
author:'Eoin Colfer',
year:2009
}
]
}
}
<?xml version="1.0" encoding="utf-8"?>
<books>
<book>
<title>The Color of Magic</title>
<author>Terry Pratchett</author>
<year>1983</year>
</book>
<book>
<title>Mort</title>
<author>Terry Pratchett</author>
<year>1987</year>
</book>
<book>
<title>And Another thing...</title>
<author>Eoin Colfer</author>
<year>2009</year>
</book>
</books>
Íà ïîìîùü ïðèõîäèò JSON!
JSON (сокращение от JavaScript Object Notation) — облегченный формат передачи данных. Обычный человек сможет читать и писать в этом формате. Он легко разбирается и генерируется компьютером. Поэтому JSON идеально подходит для структурирования и передачи данных. JSON основан на подмно-жестве стандарта JavaScript и нейтрален к языку — может использоваться практически с любым языком программирования. Формат JSON превосходит XML по эффективности передачи данных; фактически он рассматривает пары «имя/значение» как ассоциативные массивы. Значения могут быть строками, числами, массивами, объектами, логическими значениями («истина/ложь») или null.
XML vs. JSON
Пары «имя/значение», разделенные двоето-чием
Строковые значе-ния заключаются в кавычки.
Для чисел кавычки не нужны.
Объекты за-ключаются в фигурные скобки { }.
Объекты разделяются запятыми.
Массив с данными
Корневой элемент
Для обращения к информации в объектах JSON используется та же запись, как при обращении к дру-гим объектам — точечный синтаксис (.). Массивы в объектах JSON не отличаются от обычных массивов JavaScript и обладают теми же свойствами (например, length). В приведенном объекте JSON, чтобы узнать количество полученных книг нужно использовать конструкцию books.book.length. Объекты JSON имеют разную структуру, для обращения к объекту массива столько точек может и не понадобиться.
Свойства разделяются запятыми.
Многократные вхождения тегов увеличивают объем передаваемых данных.
Элементы не связаны между
собой, если не считать кор-
невого элемента. Поэтому
нам приходилось искать их
методом find().
дальше � 381
данные json
Если эта запись выглядит знакомо — это потому, что она почти не отличается от метода post, использованного нами ранее для получения данных от фор-мы. Этот простой метод представляет собой сокращенную запись для вызова метода ajax, в которой несколько параметров уже заданы заранее. В полной записи этот вызов выглядел бы так:
Да, можно.
Нам снова повезло: создатели PHP уже позаботились об этом. Продол-жим изучение базовых возможно-стей PHP, а затем посмотрим, как объединить их с другими функци-ями PHP для получения данных в формате JSON.
jQuery + JSON = ïîòðÿñàþùå
Формат JSON очень широко распространен и прост в использовании, поэтому создатели jQuery предусмотрели специальное сокращение для работы с данными JSON: метод getJSON.
$. getJSON(url_to_load, function(json) {
});URL-адрес, с которого загружаются данные
Сокраще-ние jQuery
Вызов метода getJSON
Данные возвращаются в объекте с именем json (подробности чуть позже).
Выполняемая функция обратного вызова
Но наши данные не хранятся в формате JSON — это простой
набор массивов. Можно ли преоб-разовать эти массивы в JSON?
$.ajax({
url: url_to_load,
dataType: 'json',
data: json,
success: function(json){
};
});
382 глава 9
нарушать не советуем
Íåñêîëüêî ïðàâèë PHP...
По правде говоря, никто не любит правила программирования. Но у PHP есть еще не-сколько особенностей (большей частью из области синтаксиса), которые необходимо знать для подготовки данных к использованию в jQuery. К счастью, многие из этих кон-цепций уже встречались нам в контексте JavaScript, так что изучение будет настолько бы-стрым и безболезненным, насколько это возможно…
Îñíîâíûå ïðàâèëà PHP
1. Весь код PHP должен быть заключен в теги<?php и ?> .
2. PHP может чередоваться с HTML, при этом код PHP заключается в теги <?php и ?>.
3. Все строки кода PHP должны заканчиваться точкой с за-пятой (;).
Ïðàâèëà äëÿ ïåðåìåííûõ
1. Имена всех переменных должны начинаться со знака доллара ($).
2. За $ следует как минимум одна буква или знак подчеркивания, далее идет произвольная ком би нация букв, цифр и подчеркиваний.
3. Дефисы ( - ), пробелы ( ) и любые специаль-ные символы (кроме $ и _) в именах пере-менных запрещены.
Ïðàâèëà äëÿ öèêëîâ
1. В PHP поддерживаются циклы for, while и do...while — с таким же синтаксисом, как в JavaScript.
2. В PHP также существует дополнительная раз-новидность циклов — так называемый цикл foreach, который последовательно переби-рает элементы массива до обнаружения кон-ца массива, после чего автоматически оста-навливается.
<div><span> Hello
<?php
echo "Bob"; ?>
</span></div>
<?php
for ($i = 1; $i <= 10; $i++) {
echo $i;
}
while ($j <= 10) {
echo $j++;
}
$a = array(1, 2, 3, 17);foreach ($a as $v) {
echo "Current value: $v.\n";
}
?>
<?php
$u = "USA"; // OK
$home_country = "Ireland"; // OK
$another-var = "Canada"; // Causes an error
?>
дальше � 383
данные json
Ïðàâèëà PHP (åùå íåìíîãî)...
Осталось еще несколько правил, которые помогут вам получить нужные данные, правильно отформатировать их и вывести на веб-странице.
Ïðàâèëà äëÿ ìàññèâîâ
1. Новые массивы создаются ключевым словом array (как и в JavaScript).
2. Обращения к ячейкам массивов выполняются по индексу ячейки, который указывается в ква-дратных скобках [ ] (как и в JavaScript). Индек-сы начинаются с нуля, как и в JavaScript.
3. Массивы могут быть ассоциативными, обра-щение к ячейкам осуществляется по ключу, а не по индексу. Содержимое таких массивов пред-ставляет собой пары «ключ/значение».
4. Чтобы сохранить в ассоциативном массиве но-вую пару «ключ/значение», используйте опе-ратор =>.
Ïðàâèëà óñëîâíûõ êîíñòðóêöèé
1. Команда if имеет такой же синтаксис, как в JavaScript (это относится и к условию else, и к else if).
2. Операторы сравнения работают так же, как в JavaScript.
3. Логические операторы тоже не отличаются от JavaScript, с одним дополнением: вместо операторов могут использоваться их эквива-ленты and, or и not.
Ïðàâèëà âûâîäà íà ýêðàí
1. Для вывода на экран используются ключевые слова echo и print.
2. Содержимое массива выводится командой print_r.
<?php
$my_arr2 = array('USA', 'China', 'Ireland');
echo $my_arr2[2]; // Выводит "Ireland"
$arr = array("foo" => "bar", 12 => true);
echo $arr["foo"]; // Выводит "bar"
echo $arr[12]; // Выводит true
?>
<?php
if ($x > $y){
echo "x is greater than y";
}
elseif ($x == $y) {
echo "x is equal to y";
}
else {
echo "x is smaller than y";
}
?>
<?php
echo "Bob"; print_r($my_arr2);?>
384 глава 9
всего один массив
Ôîðìàòèðîâàíèå âûâîäà ñðåäñòâàìè PHP
Хорошо, мы разобрались с основами, теперь посмотрим, что PHP может сделать для нас! Функция json_encode в PHP преобразует ассоциативный массив в строку значений, закодированную в формате JSON.
echo json_encode(array_name);
$my_array = array();
array_push($my_array, array('my_key' => 'my_val'));
Вызов этой функции PHP кодирует массив в форма-те JSON.
Создаем новый,пустой массив.
Здесь передается любая информация, добавля-емая в массив. В дан-ном случае в массив $my_array включается другой ассоциативный массив.
Вызываем функцию array_push с параме-трами.
Пара «имя/значе-ние», включаемая в этот массив
Значение записы-вается в источник вызова (браузер, вызов ajax и т. д.).
Кодируемый массив
Но прежде чем данные можно будет закодировать, они должны оказаться в одном ассоциативном массиве. Мы уже видели метод для перебора итогового набора и вы-вода всех входящих в него ассоциативных массивов. Но сейчас нам нужно взять все эти массивы и объединить их в один массив. При помощи функции PHP array_push мы можем добавлять новые элементы в конец массива.
Функция json_encode стала доступна только в PHP версии 5.2. Если вы
используете более раннюю версию PHP, либо обновите ее, либо введите
строку «json_encode PHP альтернативы» в своей любимой поисковой си-
стеме и найдите описание этой функции от создателей PHP. После этого вы
сможете написать собственную реализацию функции, чтобы пользоваться
всеми ее замечательными возможностями.
Для любознательных
Приемный массив передается в первом параметре.
дальше � 385
данные json
В: Кто придумал JSON? Создатели jQuery?
О: Нет. Дуглас Крокфорд, специалист по JavaScript из Yahoo!, изобрел JSON как то, что он назвал «обезжиренной альтернативой XML». Он приводит обоснования этой характеристики в статье: http://www.json.org/fatfree.html.
В: Разве JSON это не JavaScript?
О: И да, и нет. JSON базируется на подмножестве JavaScript, ECMA 262 Third Edition, но может использоваться в разных языках для передачи данных. Список языков, поддерживающих JSON, приведен по сайте http://www.json.org/.
В: Выходит, JavaScript и PHP имеют похожий синтаксис. По-чему же я не могу просто использовать JavaScript?
О: Как мы уже упоминали, PHP является серверным языком сценариев и может взаимодействовать с веб-сервером и базами данных от вашего имени. Код выполняется на сервере и генерирует разметку HTML, которая затем передается клиенту. JavaScript, напротив, работает только в вашем браузере, а все его взаимо-действия осуществляются на стороне клиента.
В: Понятно. Еще раз, что такое PHP?
О: PHP (рекурсивное сокращение от «PHP: Hypertext Preprocessor») — популярный, распространяемый с открытым ко-дом язык сценариев общего назначения, который особенно хорошо подходит для веб-программирования и может встраиваться в HTML.
В: Откуда взялся PHP?
О: Язык PHP появился в 1994 году. Он был создан Расмусом Лердорфом и предназначался для отображения его резюме в Интернете. В июне 1995 года был опубликован исходный код, что позволило другим разработчикам заняться обновлением и исправлением ошибок. Проект ждало большое будущее: сейчас он используется на более чем 20 миллионах сайтов по всему миру.
Вы узнали много нового о PHP, MySQL и JSON. Сейчас мы возьмемся за
большое упражнение, которое поможет сложить все фрагменты вое-
дино, так что отдохните и выпейте чашку кофе, прогуляйтесь, сделайте
что-нибудь такое, чтобы ваш мозг отдохнул и был готов к тому, что его
ожидает. А когда все будет сделано, переверните страницу, и... вперед!
Р А СС Л А Б Ь Т Е С Ь
частоЗадаваемые
вопросы
386 глава 9
длинное упражнение
Включите в файл my_scripts.js новую функцию getDBRacers, которая обращается
с вызовом к файлу service.php. Вызов должен возвращать объект JSON, а затем отобра-
жать сообщение с количеством возвращенных участников. Также измените таймер
startAJAXCalls, чтобы вместо функции getXMLRunners вызывалась эта новая
функция. Наконец, измените файл service.php, чтобы он возвращал данные участников,
прочитанные из базы данных и закодированные в формате JSON.
function startAJAXcalls(){
if(repeat){
setTimeout( function() {
..................
startAJAXcalls();
},
FREQ
);
}
}
function getDBRacers(){
$.getJSON(.......... function(.....) {
.....(json.runners........);
});
getTimeAjax();
}
my_scripts.js
Длинные упражнения
дальше � 387
данные json
<?php
$query = "SELECT first_name, last_name, gender, finish_time FROM runners order by finish_time ASC ";
$result = ..................($query);
$runners = array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
.............($runners, array('fname' => $row['first_name'], 'lname' => $row['last_name'], 'gender' => $row['gender'], 'time' => $row['finish_time']));
}
echo ............(array("runners" => ............));
exit;
function db_connection($query) {
mysql_connect('127.0.0.1', 'runner_db_user', 'runner_db_password')
OR die(fail('Could not connect to database.'));
mysql_select_db..................
return mysql_query($query);
}
function fail($message) {
die(json_encode(array('status' => 'fail', 'message' => $message)));
}
function success($message) {
die(json_encode(array('status' => 'success', 'message' => $message)));
}
?>
service.php
388 глава 9
решение длинного упражнения
В файле my_scripts.js появилась новая функция getDBRacers, которая обраща-
ется с вызовом к файлу service.php. Старая функция getXMLRunners стала лиш-
ней, ее можно удалить. Новая функция получает данные JSON, возвращенные
файлом service.php, и выводит количество полученных участников. Функция
startAJAXCalls также изменилась; теперь в ней вызывается новая функция.
Обновленный файл service.php возвращает участников, прочитанных из базы дан-
ных, закодированных в формат JSON и упорядоченных по возрастанию значений
finish_time.
function startAJAXcalls(){
if(repeat){
setTimeout( function() {
getDBRacers(); startAJAXcalls();
},
FREQ
);
}
}
function getDBRacers(){
$.getJSON("service.php", function(json) { alert(json.runners.length); });
getTimeAjax();
}
my_scripts.js
Планирование вызова новой функции
Метод jQuery getJSONобращаетсяс вызовом к файлу service.php.
Объект json содер-жит массив с именем runners, полученным при вызове метода json_encode в PHP.
Как и другие массивы, этот также имеет свойство length.
Данные, получен-ные в результате вызова getJSON
Решение длинных упражнений
дальше � 389
данные json
<?php
$query = "SELECT first_name, last_name, gender, finish_time FROM runners order by finish_time ASC ";
$result = db_connection($query);
$runners = array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
array_push.($runners, array('fname' => $row['first_name'], 'lname' => $row['last_name'], 'gender' => $row['gender'], 'time' => $row['finish_time']));
}
echo json_encode(array("runners" => $runners)); exit;
function db_connection($query) {
mysql_connect('127.0.0.1', 'runner_db_user', 'runner_db_password')
OR die(fail('Could not connect to database.'));
mysql_select_db ('hfjq_race_info');.
return mysql_query($query);
}
function fail($message) {
die(json_encode(array('status' => 'fail', 'message' => $message)));
}
function success($message) {
die(json_encode(array('status' => 'success', 'message' => $message)));
}
?>
service.php
Запрос к базе данных для получения информации об участниках
Создаем новый массив для хранения полученных данных.
Перебираем итоговый набор, получаем ассо-циативные массивы.
Полученные данные поме-щаются в ассоциативный
массив.
Ассоциативный массив ко-дируется в JSON и записы-вается в источник вызова.
Функция для взаи-модействия с базой данных
Итоговый набор возвра-
щается стороне, вы-звавшей эту функцию.Функции обработки ошибки или успеш-ного завершения в наших сценариях
390 глава 9
тест-драйв
Включите новый код в файлы service.php и my_scripts.js, откройте файл index.html в браузере. Откройте вкладку «Network» в средствах разработчика; убедитесь в том, что информация JSON загружается успешно.
Хорошо. И теперь для выво-да информации мы исполь-
зуем find и each, как при работе с XML?
Не совсем.
Мы знаем, что данные хранятся в формате JSON, потому что они были созданы в на-шем коде PHP. Пора (наконец-то) плотно заняться объектом JSON, о котором мы так много говорили, и вывести из него получен-ные данные.
Функция вы-дает количе-ство записей, возвращенных в объекте JSON.
В разделе «Network» средств разработ-чика информация JSON выводится на соответствующей вкладке.
Тест-драйв
дальше � 391
данные json
function getDBRacers(){
$.getJSON( , function(json) {
if (json.runners. > 0) {
$('#finishers_m').empty();
$('#finishers_f').empty();
$('#finishers_all').empty();
$. (json.runners,function() {
var info = '<li>Name: ' + this['fname'] + ' ' + this['lname'] + '. Time: ' + this[ ] + '</li>';
if(this['gender'] == 'm'){
$(' ').append( info );
}else if(this['gender'] == 'f'){
$('#finishers_f').append( );
}else{}
$(' ').append( info );
});
}
});
getTimeAjax();
}
Ðàáîòà ñ äàííûìè â îáúåêòå JSON
Функция PHP json_encode преобразует ассоциативный массив в строку значений, закоди-рованную в формате JSON. Далее с этими данными можно работать в коде JavaScript как с ассоциативными массивами; таким образом, мы можем перебрать их и обработать так же, как мы обрабатываем данные в других массивах.
При работе с XML нам приходилось перебирать данные для поиска следующего участника. Таким образом, после обнаружения участника нам приходилось проводить повторный поиск для проверки пола. Помните объект JSON, который возвращается функцией json_encode? Мы можем напрямую обращаться к свойствам этого объекта при помощи точечного синтак-сиса (.). Массив runners содержится в этом объекте в виде свойства. А получив доступ к мас-сиву, мы можем по ключу ассоциативного массива определить пол участника, что намного эффективнее повторного поиска.
Измените функцию getDBRunners так, чтобы она получала объект JSON от файла service.php.
Выбирайте список, в который нужно занести участника, используя условную конструкцию.
Будьте внимательны! Проверьте, содержит ли объект JSON данные хотя бы одного участника.
my_scripts.js
Возьми в руку карандаш
392 глава 9
решение упражнения
Используя условную конструкцию и информацию, полученную в объекте
JSON, можно определить, в какой список следует включить участника. Как и
прежде, все участники должны включаться в общий список all_finishers.
Для перебора всех элементов массива, возвращенного в объекте JSON, можно
воспользоваться методом each. Этот метод несколько отличается от метода
(селектор).each тем, что он позволяет перебирать содержимое массивов,
не относящихся к jQuery, таких как наш массив runners.
function getDBRacers(){
$.getJSON("service.php", function(json) {
if (json.runners.length> 0) { $('#finishers_m').empty();
$('#finishers_f').empty();
$('#finishers_all').empty();
$.each(json.runners,function() { var info = '<li>Name: ' + this['fname'] + ' ' + this['lname'] + '. Time: ' + this[‘time’] + '</li>'; if(this['gender'] == 'm'){
$('#finishers_m').append( info );
}else if(this['gender'] == 'f'){
$('#finishers_f').append(info); }else{}
$('finishers_all').append( info ); });
}
});
getTimeAjax();
}
my_scripts.js
Получаем информацию от файла service.php.
Проверяем, имеются ли данные в массиве runners.
Очищаем все списки.
Проверяем свойство
gender текущего
объекта (m или f).
Включаем участника в список all_runners.
Возьми в руку карандаш Решение
Для любознательных
дальше � 393
данные json
Измените функцию getDBRacers в файле my_scripts.js. Откройте файл index.html и убедитесь в том, что данные участников успешно загружаются из базы данных MySQL с использованием Ajax, JSON и PHP.
Информация об участ-никах, про-читанная из базы данных
Очень хорошо, мы можем получать данные, но ведь на самом деле нужно,
чтобы этот способ работал с созданной нами формой. Верно?
Очень верное замечание.
А когда это будет сделано — добро пожаловать на Гавайи! Но сначала нужно убедиться в том, что вводимые дан-ные не причинят вреда нашему приложению.
Тест-драйв
394 глава 9
данные должны быть чистыми
Èñïîëüçîâàíèå îäíîãî ôàéëà PHP äëÿ ðàçíûõ öåëåé
Мы рассмотрели два способа отправки данных серверу для обработки файлом PHP: POST и GET. При помощи условной конструкции можно определить, какой метод использовался при вызове файла PHP, и выполнить соответствующие действия. Помните скрытое поле, которое мы добавили на форму несколько страниц назад?
Ïðîâåðêà è ÷èñòêà äàííûõ â PHP
В последнее время развелось слишком много спам-ботов и хакеров, пытающихся взять под контроль ваши данные для неблаговидных целей. Никогда не доверяйте данным, введенным на веб-формах! Всегда выполняйте проверку и чистку информации, передаваемой серверу, перед вставкой в базу дан-ных. Эти операции гарантируют, что тип данных соответствует типу конкретного поля (проверка), а полученные данные не содержат информации, опасной для вашего сервера или базы данных (чист-ка). Подобные меры помогают защититься от внедрения SQL, межсайтовых сценарных атак и многих других неприятностей, о которых можно узнать в Интернете. Мы воспользуемся методами PHP, кото-рые предотвратят возможные проблемы и гарантируют, что используемые данные будут корректны.
<?php
htmlspecialchars($_POST["a"]) ; // Замена символов безопасными комбинациями
empty($_POST["b"]) ; // Метод "empty" проверяет пустые значения
preg_match('',$var); //"Регулярное выражение". $var проверяется на соответствие шаблону.
?>
Преобразует некоторые специальные символы
HTML в формат, безопасный для баз данных
Функция проверки по регулярному выражению.
Шаблоны регулярных выражений могут быть
предельно точными, что позволяет жестко
контролировать вводимые данные.
Выявление пу-стых строк
Существует много других функций, используемых для чистки данных: htmlentities, trim, stripslashes, mysql_real_escape_string и многие другие. За более подробной информацией обращайтесь к главе 6 книги «Изучаем PHP & MySQL».
<input type="hidden" name="action" value="addRunner" id="action">
Если это значение присутствует, значит выполняется отправка данных формы методом POST. В этом случае нужно выполнить функции проверки и чистки данных и убедиться, что получены все необходимые данные. Если обновить функцию getJSON для чтения участников из базы данных с параметром из URL-адреса (для объекта $_GET PHP), можно отделить и выполнить только этот фрагмент кода в файле PHP. Значит, нам придется сопровождать только один файл PHP.
$.getJSON("service.php?action=getRunners", function(json) {
Приказываем функции PHP вы-полнить код, связанный с чте-нием информации участников из базы данных.
Все прибирают на своих столах и едут в аэропорт! Мы теперь знаем, как
доделать форму, верно?
дальше � 395
данные json
Внесите в файл service.php изменения. Файл будет обрабатывать оба вида запросов, GET и POST. Включите в него функции db_connection, success и fail, которые мы создали ранее.
<?php
if ($_POST['action'] == 'addRunner') {
$fname = htmlspecialchars($_POST['txtFirstName']);
$lname = htmlspecialchars($_POST['txtLastName']);
$gender = htmlspecialchars($_POST['ddlGender']);
$minutes = htmlspecialchars($_POST['txtMinutes']);
$seconds = htmlspecialchars($_POST['txtSeconds']);
if(preg_match('/[^\w\s]/i', $fname) || preg_match('/[^\w\s]/i', $lname)) {
fail('Invalid name provided.');
}
if( empty($fname) || empty($lname) ) {
fail('Please enter a first and last name.');
}
if( empty($gender) ) {
fail('Please select a gender.');
}
$time = $minutes.":".$seconds;
$query = "INSERT INTO runners SET first_name='$fname', last_name='$lname', gender='$gender', finish_time='$time'";
$result = db_connection($query);
if ($result) {
$msg = "Runner: ".$fname." ".$lname." added successfully" ;
success($msg);
} else { fail('Insert failed.');} exit;
}elseif($_GET['action'] == 'getRunners'){
$query = "SELECT first_name, last_name, gender, finish_time FROM runners order by finish_time ASC ';
$result = db_connection($query);
$runners = array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
array_push($runners, array('fname' => $row['first_name'], 'lname' => $row['last_name'], 'gender' => $row['gender'], 'time' => $row['finish_time']));
}
echo json_encode(array("runners" => $runners));
exit;
}
service.php
Проверяем, было ли отправлено
на сервер значение addRunner
(из скрытого поля).
Чистка данных в массиве $_POST
Проверка данных подтверж-
дает, что поля формы были
заполнены.
Если проверка не прошла, вызывается функция fail.
Приказываем базе данных
вставить новую запись… …и проверить, успешно была выполнена опе-рация или нет.
Проверяем, было ли отправлено в строке URL-адреса значение getRunners.
Получаем и воз-вращаем данные участников.
Готово к употреблению
396 глава 9
Тест-драйв
гавайи ждут...
function getDBRacers(){
$.getJSON("service.php?action=getRunners", function(json) {
if (json.runners.length > 0) {
$('#finishers_m').empty();
.
.
}
});
getTimeAjax();
}
Потрясающе! Садимся на самолет,
а остальное добьем уже на пляже...
Задание!
Обновите вызов getJSON, чтобы в нем передавался параметр URL-адреса action со значением getRunners. По этому параметру файл service.php узнает, что он должен вернуть данные участников.
Обновите файлы service.php и my_scripts.js, откройте файл index.html в браузере. Убедитесь в том, что данные участников были загружены успешно. Вы также можете ввести данные новых участников в форме на новой вкладке.
my_scripts.js
дальше � 397
данные json
Âàø èíñòðóìåíòàðèé jQuery/Ajax/PHP/MySQL
Глава 9 осталась позади. Вы освоили азы работы с PHP, MySQL и JSON, а также расширили свои познания в Ajax.
MySQLПозволяет
хранить информацию
в базах данных и таблицах, с вы
-
полнением операций чтения и за-
писи информации на языке SQL.
SQLЯзык запросов для
взаимодействия
с приложениями баз данных (таки-
ми как MySQL).
PHPСерверный язык сценариев для обработки содержимого веб-страницы до ее передачи клиент-скому браузеру.Сценарий PHPТекстовый файл с кодом PHP
для выполнения операций на веб-сервере.
с пр
ми как MySQL).
JSONФункция getJSON используется для
получения от сервера данных, за-
кодированных в формате JSON.
Для отправки данных формой ис-
пользуется метод POST. Перед
отправкой данные необходимо
отформатировать функцией
serializeArray.
<?php ?>Теги, в которые должен быть заключен весь код PHP в ваших сценариях PHP.echoКоманда PHP для отправки выходных данных в окно браузера. Синтаксис:echo ‘Hello World’;World ;
$_POSTСпециальная переменная для хра-нения данных формы. json_encode
Команда преобразует массив в данные, закодированные в фор-мате JSON (необходимо по прави-лам jQuery).
ГЛА
ВА 9
jQuery UI10
Переработка форм
Пользователи и их данные — жизнь и смерть веб-приложений. Ввод данных пользователем — серьезная задача, которая может отнять много времени у веб-разработчика. Вы уже видели, как jQuery упрощает построение веб-приложений, использующих Ajax, PHP и MySQL. Теперь давайте посмотрим, как jQuery упрощает построение пользовательского интерфейса форм для ввода данных пользователем. Заодно вы узнаете много полезного о jQuery UI — официальной библиотеке пользовательского интерфейса для jQuery.
Мне нравится твоя форма. Может,
зайдем ко мне, побол-таем об интерфейсах?
Ух... Надеюсь, моя форма пройдет
проверку.
400 глава 10
кто видел снежного человека?
Доктор Паттерсби и доктор Гимли стремятся собрать как можно больше информации о встречах с крип-тидами по всему миру. Их сайт cryptozoologists.org пользуется уважением как у профессиональных крип-тозоологов, так и у любителей. У них есть для вас особо важное поручение: обновление устаревшей формы для ввода информации о встречах с криптидами.
Криптиды — существа, неизвест-ные науке или не признаваемые
научным сообществом. Сбор данных о встречах с ними играет важней-шую роль в наших исследованиях.
Знаменитые криптиды — снежный человек, чупакабра и лохнесское чудовище. Нам
нужна более совершенная форма для ввода информации о том, где люди видели этих
существ.
Cryptozoologists.org íóæäàåòñÿ â ïåðåðàáîòêå
Немедленно уберите репортеров!
Доктор Гимли
Доктор Паттерсби
??
??Криптозоологи хотят избавиться от своей старой, неудобной формы HTML.
400 гглава 10
Сообщение о наблюдении криптида
Пожалуйста, введите подробное описание своей встречи с крип-
тидом под своими контактными данными.
Заполните форму и щелкните на кнопке "Enter"
для отправки данных.
Дата наблюдения:
Где вы видели существо:
Тип существа:
Описание существа:
ReptileMammal
Bird
Внешний вид и поведение
формы не внушает эн-
тузиазма. Она сделана на
уровне конца 1990-х годов.
Нет никаких визуальных подсказок, которые бы помогали пользователю вводить данные. Впро-чем, возможности HTML по этой части невелики. В результате доктора получают массу некор-ректных данных.
дальше � 401
jquery ui
Íîâàÿ ôîðìà HTML
Сообщение о наблюдении криптидов
ИНФОРМАЦИЯ О ВСТРЕЧЕ С КРИПТИДОМ
Дата наблюдения:
Тип: Дистанция (в футах): Вес:Рост:Окрас кожи/меха:
Данные о месте встречи
Широта:Долгота:
Дополнительная информация:
Месяц
В действующей форме используется
текстовое поле, что повышает риск
некорректного ввода. Мы хотим,
чтобы пользователь выбирал дату
в календаре, чтобы информация была
по возможности точной.
Нам хочется,
чтобы пользо-
ватели вводили
значения, двигая
ползунок. Пользо-
вателям удобно,
а мы получаем
точную инфор-
мацию.
Можно ли улучшить внешний вид
кнопки? «Угловатость» выглядит
несовременно.
Как насчет системы сме-шения цветов?
RGB
В существующей форме данные вводятсяпри помощи кнопок-переключателей;можно ли использовать что-нибудьпосимпатичнее?
Млекопитающее
Enter
Ниже приведен эскиз того, как, по мнению криптозоологов, должна выглядеть новая форма с несколькими дополнительными замечаниями.
Криптозоологи поставили перед нами непростую задачу. Фактически они хотят построить такой же пользовательский интерфейс, как в настольном приложении. Как вы думаете, jQuery поможет ее решить?
Мозговой
штурм
402 глава 10
разговор в офисе
ДжимФрэнк Джо
Фрэнк: Я видел. Сейчас они используют форму HTML, но воз-можностей HTML и CSS недостаточно для новой формы, ко-торую они от нас требуют.
Джим: И не говори. Когда-нибудь пытались применять к эле-ментам форм стили CSS? Визит к стоматологу и то приятнее.
Фрэнк: Да уж, а насчет jQuery... Я пока не видел в jQuery ни-чего, что помогло бы нам строить такие компоненты интер-фейса.
Джо: Придется что-нибудь придумать. Пользователи уже при-выкли к современным компонентам, так что мы должны най-ти способ их создавать.
Фрэнк: Вероятно, для их реализации нам придется использо-вать комбинацию JavaScript, jQuery и CSS.
Джим: Сколько логики придется написать... Только для вре-менного окна календаря потребуется множество строк кода и сложные стили CSS.
Джо: Хм... Для таких задач должен существовать какой-нибудь модуль расширения jQuery.
Джим: Точно, модули расширения! Мы уже использовали та-кой модуль пару глав назад для создания вкладок на странице результатов гонки. Значит, вкладки — это еще не все?
Джо: Да, если в jQuery отсутствует функциональность, не-обходимая разработчику, то разработчик может написать мо-дуль расширения и опубликовать его для использования в со-обществе jQuery. Этим он избавляет других разработчиков от лишней работы.
Джим: Так может, какой-нибудь разработчик или группа раз-работчиков уже занимались этой задачей?
Фрэнк: Это существенно упростило бы нам жизнь.
Джо: Давайте пороемся на jQuery.com и посмотрим, что нам удастся найти.
Парни, вы уже видели эскиз формы для криптозоологов?
дальше � 403
jquery ui
А как было бы замечательно, если бы существовала библиотека модулей расширения jQuery для пользовательского интерфейса...
Но это, конечно, всего лишь мечты…
404 глава 10
знакомство с jquery ui
jQuery UI ýêîíîìèò âðåìÿ è ñèëû
К счастью для всех разработчиков, в jQuery имеется официальная библиотека модулей расширения пользовательского интерфейса для подобных проектов. Эта библиотека называется jQuery UI, и в нее входят три основных типа модулей расширения базовой функциональности jQuery: эффекты, взаимо-действия и виджеты.
ÂèäæåòûÂçàèìîäåéñòâèÿÝôôåêòû
jQuery UI дополняет jQuery многими новыми эффекта-ми. Заставьте свои элемен-ты прыгать, взрываться, пульсировать или трястись! В jQuery UI также включены функции плавности — слож-ные математические опера-ции, которые делают ани-мацию более реалистичной.
Взаимодействия наделяют веб-приложения более слож-ным поведением. Для элемен-тов можно разрешить перета-скивание мышью, сортировку и т. д.
Виджет ( widget) представля-ет собой самостоятельный компонент, который рас-ширяет функциональность веб-приложения. Виджеты экономят время и сокращают сложность кода, и при этом в вашей программе используют-ся работоспособные, эффек-тивные элементы пользова-тельского интерфейса.
Опробуйте некоторые эффекты, взаимодействия и виджеты jQuery UI. Посетите следующие URL-адреса и выполните инструкции.
URL Инструкции
http://jqueryui.com/demos/animate/#default Щелкните на кнопке Toggle Effect.
http://jqueryui.com/demos/effect/default.html Выберите эффект из раскрывающегося списка, щелкните на
кнопке Run Effect.
http://jqueryui.com/demos/
draggable/#default
Нажмите кнопку мыши в прямоугольнике с надписью «Drag
me around». Перемещая мышь, двигайте прямоугольник
в выделенной области экрана.
http://jqueryui.com/demos/accordion/#default Щелкая в разных секциях, проследите за тем, как они разво-
рачиваются и сворачиваются.
http://jqueryui.com/demos/dialog/#animated Щелкните на кнопке Open Dialog, чтобы открыть пользова-
тельское диалоговое окно jQuery UI. Намного лучше обыч-
ного, скучного окна сообщения JavаScript, не правда ли?
Механизм модулей расширения jQuery позво-
ляет веб-разработчикам расширять базовую
функциональность библиотеки jQuery.
В работе с пользова-тельским интерфейсом в этой главе наше вни-мание будет уделяться виджетам.
Тест-драйв
дальше � 405
jquery ui
Взаимодействие: у элемента появляют-ся маркеры перетаскивания, при помо-щи которых пользователь изменяет его размеры.
Виджет: отображение текущего состоя-ния (в процентах) некоторого процесса.
Взаимодействие: элемент DOM стано-вится приемником для перетаскивае-мых элементов.
Эффект: элемент увеличивается в раз-мерах и рассеивается, словно облачко дыма.
Взаимодействие: изменение порядка элементов посредством перетаскива-ния.
Виджет: создание набора сворачива-емых областей для организации веб-содержимого.
Виджет: вывод списка возможных зна-чений при заполнении поля пользова-телем.
Puff
Explode
Sor table
Progressbar
Droppable
Autocomplete
Blind
Accordion
Resizable Эффект: элемент распадается на части, которые разлетаются в разных направ-лениях.
Эффект: элемент скользит вверх или вниз, словно жалюзи.
Соедините каждый модуль расширения jQuery UI с описанием типа и дей-ствия. Подсказка: если у вас возникнут сомнения, поэкспериментируйте с демонстрационным сайтом Test Drive (см. предыдущую страницу).
Кто и что делает?аеааеееееееееееееееее
406 глава 10
решение упражнения
Соедините каждый модуль расширения jQuery UI с описанием типа и действия.
Puff
Explode
Sor table
Progressbar
Droppable
Autocomplete
Blind
Accordion
Resizable
Взаимодействие: у элемента появляются маркеры перетаскивания, при помощи которых пользователь изменяет его раз-меры.
Виджет: отображение текущего состоя-ния (в процентах) некоторого процесса.
Взаимодействие: элемент DOM стано-вится приемником для перетаскиваемых элементов.
Эффект: элемент увеличивается в раз-мерах и рассеивается, словно облачко дыма.
Взаимодействие: изменение порядка эле-ментов посредством перетаскивания.
Виджет: создание набора сворачива-емых областей для организации веб-содержимого.
Виджет: вывод списка возможных значе-ний при заполнении поля пользователем.
Эффект: элемент распадается на части, которые разлетаются в разных направ-лениях.
Эффект: элемент скользит вверх или вниз, словно жалюзи.
Кто и что делает?аеааеееееееееееееееее
Решение
дальше � 407
jquery ui
http://jqueryui.com/download
Задание!
Откройте в браузере страницу загрузки jQuery UI.1
Выберите загружаемые компоненты.2
Выберите тему для загрузки.3
Нам потребуются толь-ко базовые компоненты и виджеты; установите показанные флажки.
Одно из главных достоинств jQuery UI — темы оформления. Группа разработчиков jQuery UI включила весь код CSS для создания интерфейса профессионального уровня. Вы даже можете создать собственную тему оформления при помощи приложения jQuery UI «theme roller». Галерею всех тем jQuery UI можно просмотреть по URL-адресу http://jqueryui.com/themeroller/#themeGallery
Выберите тему Sunny.
Нажмите кнопку Download.4
Итак, я загрузил библио теку jQuery UI! Как
теперь начать с ней работать?
Распакуйте архив и включите библиотеку в папку проекта.На следующей странице описана структура jQuery UI.
Прежде чем сделать что-либо с jQuery UI, необходимо настроить нужные ком-поненты, выбрать тему и загрузить ее копию. Выполните следующие действия:
408 глава 10
структура jquery ui
Ñîäåðæèìîå ïàêåòà jQuery UI
Ñïèñîê çàäà÷ ïðîåêòà
1. Создать календарь для выбора даты наблюдения.2. Создать более привлекательные кнопки-переключатели для выбора типа
существа.3. Создать ползунки для ввода расстояния, веса и роста существа, широты
и долготы места наблюдения.4. Создать компонент для выбора цвета существа.5. Создать более симпатичную кнопку отправки данных.
После загрузки и распаковки jQuery вы увидите, что пакет имеет следующую структуру:
index.htmldevelopment-bundle
jquery-ui-1.8.16.custom
jquery-1.6.2.min.js
jquery-ui-1.8.16.custom.css
jquery-ui-1.8.16.custom.min.js
images
Выбранная вами тема находится в папке css.
Чтобы виджеты jQuery UI выглядели нормально, в секции head формы sightings.html должна присутствовать ссылка на этот файл.
На момент напи-сания книги послед-няя версия jQuery UI имела номер 1.8.16.
В форму sightings.html необходимо включить секцию script со ссылкой на этот файл.
Разработчики UI позаботились о том, чтобы у вас была копия библио-теки jQuery.
Мы включили папку jQuery UI в архив кода, загруженный вами в начале книги. Вы найдете ее в папке end внутри папки ch10.
jQuery UI делает многое за вас, но для создания новой формы нам придется решить ряд промежуточных задач. Перед вами контрольный список того, что мы должны сделать.
css
sunny
js
дальше � 409
jquery ui
Ïîñòðîåíèå êàëåíäàðÿ
<input type="text" name="sighting_date">
Возьмите обычное поле HTML input.3
Создайте тег <script> со ссылкой на jQuery UI.2
Включите в тег <input> атрибут id со значением "datepicker".4
Откройте файл в своем любимом браузере и щелкните на поле input.6
Создайте файл JavaScript и включите следующий фрагмент между фигурными скобками $(document).ready(function(){}.
5
<input type="text" name="sighting_date" id="datepicker">
<link type="text/css" href="jquery-ui-1.8.16.custom/css/sunny/jquery-ui-1.8.16.custom.css" rel="stylesheet" />
<script src="jquery-ui-1.8.16.custom/js/jquery-ui-1.8.16.custom.min.js"></script>
$('#datepicker').datepicker();
Создайте ссылку на CSS-файл jQuery UI:1
Вот и все! Вы
только что до-
бавили на форму
интерактивный
виджет.
Вы не поверите, как легко включаются виджеты jQuery UI в форму HTML. Начнем с календаря:
410 глава 10
работаем эффективнее, а не больше
Здорово, все происходит само собой, а мне достаточно написать немного кода HTML и jQuery. Но я вынуждена использовать конкрет-ный вариант оформления и функций календаря?
А если я захочу что-нибудь другое?
Интер-претатор
JavaScript
Модель DOM- страницы
$("#datepicker").datepicker();
Как и любой другой код jQuery, написанный вами, datepicker использует селектор и метод.
1
Интерпретатор JavaScript запрашивает у DOM элемент с идентификатором datepicker.
2DOM получает выбранный элемент, выполняет для него элемент datepicker и возвращает интерпретатору.
3
Код jQuery
Засценой
Пожалуйста.
Дай мне элемент стра-ницы с идентификатором
datepicker.
Не беспокойтесь, у вас есть выбор.
Давайте посмотрим, что можно сделать.
Основные события происходят здесь, в методе datepicker.
Метод datepicker приказывает интерпретатору JS построить календарь «на ходу», вместе со всем кодом HTML, CSS и встроенной интерактивностью.
4
Виджет, так не-ожиданно появляю-щийся на странице, представляет со-бой таблицу, вло-женную в несколько областей div.
Íåçàìåòíîå âìåøàòåëüñòâî jQuery UI
На первый взгляд происходящее кажется каким-то волшебством, но в действительности jQuery UI представляет собой хорошо спроектированный и написанный блок кода, который не придется писать вам. Давайте разберемся в том, как он работает.
дальше � 411
jquery ui
$("#datepicker").datepicker({ stepMonths: 3});
$("#datepicker").datepicker({ changeMonth: true});
Èçìåíåíèå ïàðàìåòðîâ âèäæåòà
Кнопка для перехода к следующему месяцу. При каждом щелчке гене-рируется новая таблица для соответствующего месяца.
Кнопка для пере-
хода к предыду-
щему месяцу
Текущая дата выделяется другим цветом.
Немного повозившись с изучением виджета datepicker, вы увидите, что он обладает многочисленными дополнительными возможностями, которые вы можете настроить по своему усмотрению.
Íàñòðîéêà âèäæåòà datepicker
w
Если в виджете открыт кален-дарь на август, то кнопки перехода сдвинуты на три месяца вперед или назад соответственно.
Виджет datepicker со-держит множество настраиваемых па-раметров. Параметр stepMonths определяет расстояние перехода в месяцах.
Так как библиотека jQuery UI построена на базе jQuery, вам не придется писать большой объем кода, чтобы приспособить виджет datepicker к вашим потребностям. На момент на-писания книги виджет datepicker поддерживал 46 разных настраиваемых параметров.
Если задать параметру
changeMonth значение true,
то пользователь сможет
выбрать месяц в раскрываю-
щемся списке.
Напишите фрагмент кода, который позволит пользователю виджета datepicker выбрать и год, и месяц в раскрывающемся списке. Подсказка: если вы задае-те значения нескольких параметров, разделите их запятыми.
Упражнение
412 глава 10
решение упражнения
Напишите фрагмент кода, который позволит пользователю виджета datepicker вы-брать и год, и месяц в раскрывающемся списке. Подсказка: если вы задаете значения нескольких параметров, разделите их запятыми.
$(‘#datepicker’).datepicker({ changeMonth: true, changeYear: true});
Найдите файл sightings_begin.html в папке begin внутри папки ch10. Сохраните его под именем sightings_end.html в папке end главы 10. Включите код, выделенный ниже жирным шрифтом, в файлы sightings_end.html и my_scripts.js.
<head> <title>Submit Your Cryptid Sighting</title> <link rel="stylesheet" type="text/css" href="style/form.css" /> <link type="text/css" href="jquery-ui-1.8.16.custom/css/sunny/jquery-ui-1.8.16.custom.css" rel="stylesheet" /></head>
<h3>Date of Sighting:</h3> <input type="text" name="sighting_date" id="datepicker" />
В начале файла sightings_end.html
$(document).ready(function(){
$('#datepicker').datepicker({ changeMonth: true, changeYear: true});
});//end doc ready
my_scripts.js
<script src="scripts/jquery-1.6.2.min.js"></script> <script src="scripts/my_scripts.js"></script> <script src="jquery-ui-1.8.16.custom/js/jquery-ui-1.8.16.custom.min.js"></script> </body></html> Ближе к концу файла
sightings_end.htmlВключаем библиотеку jQuery UI,
чтобы пользоваться ее классными
возможностями пользовательского
интерфейса.
Чтобы виджеты выглядели так, как положено, необхо-димо подключить CSS-файл jQuery UI.
Код datepicker
sightings_end.html
Готово к употреблению
дальше � 413
jquery ui
1. Создать календарь для выбора даты наблюдения.
2. Создать более привлекательные кнопки-переключатели для выбора типа существа.
3. Создать ползунки для ввода расстояния, веса и роста существа, широты и долготы места наблюдения.
4. Создать компонент для выбора цвета существа.
5. Создать более симпатичную кнопку отправки данных.
Введите код с предыдущей страницы, откройте файл sightings_end.html в своем люби-мом браузере и протестируйте виджет. Пощелкайте на кнопках «вперед» и «назад», откройте списки месяца и года и убедитесь в том, что все работает нормально.
Êàëåíäàðü ðàáîòàåò!
Виджет datepicker работает именно так, как требуется.
Опции changeMonth Опции changeMonth и changeYear тоже и changeYear тоже работают.работают.
Âû÷åðêèâàåì...
Пункт 1 выполнен, переходим к пункту 2.
Тест-драйв
414 глава 10
кнопка, на которой хочется щелкнуть
Ñòèëüíûå êíîïêè
$( "#radio" ).buttonset();
<div id="radio">
<input type="radio" id="radio1" name="radio" />
<label for="radio1">Choice 1</label>
<input type="radio" id="radio2" name="radio" />
<label for="radio2">Choice 2</label>
<input type="radio" id="radio3" name="radio" />
<label for="radio3">Choice 3</label>
</div>
Размещаем кнопки-пере-ключатели внутри кон-тейнерного элемента.
Ãðóïïèðîâêà âèäæåòîâ button
Метод buttonset автоматически
группирует кнопки и вызывает метод
button для каждого элемента.
Метод button преобразует классическую кнопку-переклю-чатель HTML в эффектную, более интерактивную кнопку.
<input type="radio" id="radio1" name="radio" />
<label for="radio1">Choice 1</label>
Виджет button при помощи стилевого оформления придает элементу label вид кнопки.
Этот элемент будет обнов-лен при щелчке пользователя.
$( "#radio1" ).button();
В коде jQuery выбираем контейнерный элемент.
Для построения групп кнопок в jQuery UI существует ме-тод buttonset, который преобразует отдельные элементы в группу по ссылке на контейнерный элемент группы.
Не забудьте, что код разметки кнопок input должен находиться в теге HTML.
Код HTML одной кнопки-переключателя
И соответствующая команда jQuery
Что значит «более привлекательные» применительно к кнопкам? В основном это вопрос стиля: если кнопка будет хорошо смотреться, пользователю захочется щелкнуть на ней. В библиотеку jQuery UI входит чрезвычайно полезный виджет button. Его метод button помогает создавать более привлекательные элементы форм — кнопки отправки данных, переключатели и флажки.
дальше � 415
jquery ui
Расставьте магниты в правильном порядке, чтобы сложить из них код набора
кнопок для выбора типа существа. Мы разместили несколько фрагментов за вас.
Развлечения с магнитами
my_scripts.js
<input type="radio" id="radio1" name="creature_type" />
<div id="type_select">
sightings_end.html
$( "#type_select" ).buttonset();
<label for="radio1">Chupacabras</label>
</div><input type="radio" id="radio2" name="creature_type" />
<label for="radio2">Jersey Devil</label>
<input type="radio" id="radio3" name="creature_type" />
<label for="radio3">Loch Ness Monster</label>
<i t
<input type="radio" id="radio4" name="creature_type" />
<label for="radio4">Sasquatch</label>
416 глава 10
решение упражнения
Мы создали набор кнопок-переключателей, соответствующих
общей теме формы.
Развлечения с магнитами. Решение
$( "#type_select" ).buttonset();
my_scripts.js
<input type="radio" id="radio1" name="creature_type" />
<label for="radio1">Chupacabras</label>
</div>
<div id="type_select">
sightings_end.html
<input type="radio" id="radio2" name="creature_type" />
<label for="radio2">Jersey Devil</label>
<input type="radio" id="radio3" name="creature_type" />
<label for="radio3">Loch Ness Monster</label>
<input type="radio" id="radio4" name="creature_type" />
<label for="radio4">Sasquatch</label>
В папке code мы доба-вили остальные кнопки (Yeti и Other). Здесь они не приведены из-за нехватки места.
дальше � 417
jquery ui
Берем обычные кнопки-переключатели HTML…
…и превращаем их в элегантный набор современ-ных кнопок.
Включите приведенные строки кода в файлы sightings_end.html и my_scripts.js. Затем от-кройте страницу в любимом браузере и убедитесь в том, что она работает правильно.
1. Создать календарь для выбора даты наблюдения.
2. Создать более привлекательные кнопки-переключатели для выбора типа существа.
3. Создать ползунки для ввода расстояния, веса и роста существа, широты и долготы места наблюдения.
4. Создать компонент для выбора цвета существа.
5. Создать более симпатичную кнопку отправки данных.
Как видите, ничего сложного. Что там следующее в списке?
Тест-драйв
418 глава 10
ограничение вводимых данных
Îãðàíè÷åíèå ââîäà ÷èñëîâûõ äàííûõ
Расширения jQuery UI позволяют использовать для ввода данных ползунки, которыми пользователь управляет при помощи мыши или клавиатуры. Эти элементы также помогают контролировать диа-пазон вводимых чисел. Как вы уже видели, при наличии библиотеки jQuery UI построить виджет для работы с календарем проще простого. С ползунком (виджет slider) дело обстоит ничуть не сложнее.
$("#slide_me"). slider();<div id="slide_me"></div>
$( "#slide_me" ).slider({
value:0,
min: 0,
max: 100,
step: 5,
orientation: 'vertical'
});
Пользователь перемещает ползунок
при помощи указателя мыши или кла-
виш управления курсором.
Ползунки также поддерживают многочисленные возможности настройки. Предпо-ложим, пользователь должен ввести набор чисел. Наименьшее допустимое значение равно 0, а наибольшее 100. Кроме того, пользователи должны вводить числа с прира-щением 5. Соответствующие значения параметров виджета slider выглядят так:
При перемещении рукоятки по шкале
изменяется текущее значение элемента.
Параметр value задает начальное значение пол-зунка.
Параметр min задает наимень-шее значение, которое может быть введено пользователем.
Параметр max задает наибольшее значение, которое может быть введено пользователем.Параметр step задает величину приращения.
Параметр orientation определяет ориентацию виджета (горизонталь-ная или вертикальная).
Создание ползунка в файле HTML
Сопутствующий код jQuery
дальше � 419
jquery ui
<input type="text" id="my_value" readonly="readonly"/>
<div id="slide_me"></div>
$( "#slide_me" ).slider({
slide: function( event, ui ) {
$( "#my_value" ).val( ui.value);
}
});
$( "#my_value" ).val( $( "#slide_me" ).slider( "value" ));
Нужно связать ползунок с одним из обработчиков событий вид-жета slider.Мы уже видели, как задаются параметры виджета, но не рассматривали другую, полезную возможность jQuery UI. Многие компоненты jQuery поддерживают об-работчики событий, ползунок не является исключением. На момент написания книги виджет slider из библиотеки jQuery UI поддерживал пять обработчиков со-бытий: create, start, slide, change и stop. Чтобы связать ползунок с полем ввода формы, воспользуемся обработчиком события slide.
У виджета slider есть немало по-лезных параметров, но как перене-
сти значение, введенное ползунком, в поле ввода формы?
Ñöåíàðíûé êîä jQuery äëÿ âèäæåòà slider
Ðàçìåòêà HTML äëÿ âèäæåòà slider
Это обработчик события slide. Событие slide инициируется при перемеще-нии ползунка.
Событие slide свя-зывается с функ-цией обратного вызова. При выпол-нении эта функция задает значение поля ввода мето-дом jQuery val.
Когда пользователь двигает ползунок, вызывается функ-ция, а элемент input обнов-ляется текущим значением ползунка.
The input "my_value"
The slider "slide_me"
Чтобы запретить пользователю
вводить числа, используйте значение
«readonly».
420 глава 10
длинное упражнение
Заполните пропуски в коде полей input. Криптозоологи оставили замечания по поводу настройки ползунков.
Расстояние от существа (в футах):
Начальное значение = 0.
Минимальное расстояние = 0.
Максимальное расстояние = 500.
Приращение = 10 футов.
my_scripts.js
$( "#slide_dist" ).slider({
slide: function( event, ui ) {
$( "#distance" )
}
});
<h3>Distance from Creature (in ft.):</h3>
<input type="text" id=" " class="just_display" name="creature_distance" readonly="readonly"/>
<div id=" "></div>
</div>
</div>
sightings_end.html
Длинные упражнения
дальше � 421
jquery ui
Вес существа (в фунтах):
Начальное значение = 0.
Минимальный вес = 0.
Максимальный вес = 5000.
Приращение = 5 фунтов.
my_scripts.js my_scripts.js
$( " " ).slider({
slide: function( event, ui ) {
$( " " ).val( ui.value);
}
});
$( "#slide_weight" ).slider({
$( "#weight" ).val( ui.value);
}
});
sightings_end.html
<h3>Creature Weight (in lbs.):</h3>
<input type="text" id="weight" class="just_display" name="creature_weight" readonly="readonly"/>
<div id=" "></div>
<h3>Creature Height (in ft.):</h3>
<input type="text" id="height" class="just_display" name="creature_height" readonly="readonly"/>
<div id="slide_height"></div>
Рост существа (в футах):
Начальное значение = 0.
Минимальное значение = 0.
Максимальное значение= 20.
Приращение = 1 фут.
422 глава 10
решение упражнения
Заполните пропуски в коде полей input. Криптозоологи оставили свои замечания по поводу настройки ползунков.
Расстояние от существа (в футах):
Начальное значение = 0.
Минимальное расстояние = 0.
Максимальное расстояние = 500.
Приращение = 10 футов.
my_scripts.js
$( "#slide_dist" ).slider({
slide: function( event, ui ) {
$( "#distance" )
}
});
<h3>Distance from Creature (in ft.):</h3>
<input type="text" id=" " class="just_display" name="creature_distance" readonly="readonly"/>
<div id=" "></div>
</div>
</div>
sightings_end.html
value:0,
step: 10,
.val( ui.value);
max:500,min:0,
distance
slide_dist
Решение длинных упражнений
дальше � 423
jquery ui
Вес существа (в фунтах):
Начальное значение = 0.
Минимальный вес = 0.
Максимальный вес = 5000.
Приращение = 5 фунтов.
my_scripts.js my_scripts.js
$( " " ).slider({
slide: function( event, ui ) {
$( " " ).val( ui.value);
}
});
$( "#slide_weight" ).slider({
$( "#weight" ).val( ui.value);
}
});
sightings_end.html
<h3>Creature Weight (in lbs.):</h3>
<input type="text" id="weight" class="just_display" name="creature_weight" readonly="readonly"/>
<div id=" "></div>
<h3>Creature Height (in ft.):</h3>
<input type="text" id="height" class="just_display" name="creature_height" readonly="readonly"/>
<div id="slide_height"></div>
Рост существа (в футах):
Начальное значение = 0.
Минимальное значение = 0.
Максимальное значение= 20.
Приращение = 1 фут.
slide_weight
#slide_heightvalue:0,min:0,
value:0,
step: 1,max:20,
min:0,
slide: function( event, ui ) {#height
step: 10,max:5000,
424 глава 10
тест-драйв
Включите код из длинного упражнения на предыдущих страницах в свои файлы, после чего откройте файл sightings_end.html в своем любимом браузере. Проверьте, как работают ползунки, с использованием мыши и клавиатуры (клавиши со стрел-ками влево и вправо должны изменять состояние ползунка на одно приращение).
Теперь пользовате-ли могут вводить данные, перемещая рукоятки ползун-ков, а криптозоо-логи могут лучше контролировать вводимые данные.
Осталось построить еще два числовых ползунка: для ввода широты и долготы... И мы сможем вычеркнуть еще один пункт в списке задач!
Тест-драйв
дальше � 425
jquery ui
Но широта и долгота могут прини-мать отрицательные и дробные значения (например, 0.00001). Работает ли виджет
slider с такими числами?
Заполните пропуски в коде jQuery, чтобы создать на форме ползунки для ввода ши-
роты и долготы. Ползунок широты должен работать в диапазоне от –90 до 90 с при-
ращением 0.00001. Ползунок долготы должен работать в диапазоне от –180 до 180
с приращением 0.00001.
value:0, slide: function( event, ui ) { $( " " ).val( ui.value); } });
value:0, slide: function( event, ui ) { $( " " ).val( ui.value); } });
my_scripts.js
Создатели jQuery UI подумали и об этом.Виджет slider может работать как с отрицательными, так и с дробными числами. Отрицательные числа могут указываться в качестве текущего, максимального и минимального значения. Попробуйте и посмотрите, как это выглядит в действии.
Возьми в руку карандаш
426 глава 10
решение упражнения
Заполните пропуски в коде jQuery, чтобы создать на форме ползунки для ввода широты и дол-
готы. Ползунок широты должен работать в диапазоне от –90 до 90 с приращением 0,00001.
Ползунок долготы должен работать в диапазоне от –180 до 180 с приращением 0,00001.
value:0, slide: function( event, ui ) { $( " " ).val( ui.value); } });
value:0, slide: function( event, ui ) { $( " " ).val( ui.value); } });
my_scripts.js
$( "#slide_lat" ).slider({
min: -90,max: 90,step: 0.00001,
latitude
longitude
step: 0.00001,
min: -180,max: 180,
$( "#slide_long" ).slider({
Что дальше? Нужно создать интерфейс для ввода цвета существа. Компонент определения цвета будет состоять из ползунков, соответствующих трем цветовым составляющим (красная, зеленая и синяя).
К настоящему моменту мы вычеркнули уже несколько пунктов списка задач.
1. Создать календарь для выбора даты наблюдения.
2. Создать более привлекательные кнопки-переключатели для выбора типа существа.
3. Создать ползунки для ввода расстояния, веса и роста существа, широты и долготы места наблюдения.
4. Создать компонент для выбора цвета существа.
5. Создать более симпатичную кнопку отправки данных.
Возьми в руку карандаш Решение
дальше � 427
jquery ui
Ñîçäàíèå öâåòà ïî òðåì ñîñòàâëÿþùèì
Ïîëçóíêè äîëæíû ðàáîòàòü ïî òîìó æå ïðèíöèïó
Значения интенсивности красного, зеленого и синего лежат в диапазоне от 0 до 255. Когда все три интенсивности находятся на минимуме (то есть равны 0), получается черный цвет. При максимальных значениях цветовых составляющих (все три состав-ляющие равны 255) получается белый цвет.
Когда красная, зеленая и синяя со-ставляющие равны 0, получается черный цвет.
Когда красная составляющая равна 255 (а зеленая и синяя равны 0), получается красный цвет.
Когда зеленая составляющая рав-на 255 (а красная и синяя равны 0), получается зеленый цвет.
Когда синяя составляющая равна 255 (а красная и зеленая равны 0), получается синий цвет.
Итак, мы должны построить три ползунка для трех цветовых составляющих: красной, зеленой и синей. Затем текущие значения всех ползунков объединяются в один цвет. Давайте посмот-рим, что должен делать каждый из трех виджетов slider.
Когда красная, зеленая и синяя составляющие равны 255, полу-чается белый цвет.
Цвет элемента div#swatch определяется комбинацией значений трех ползунков.
Образец цвета должен изменять-
ся каждый раз, когда пользователь
перемещает один из ползунков.
Значения ползунков лежат в диапазоне 0–255.
Полям input присваиваются иден-тификаторы CSS red_val, green_val и blue_val.Цвет
#red
#green
#blue
#swatch
RGB
RG
B
RGB
RGB
RGB
RGB
428 глава 10
готовый код
//color slider styles #slide_dist, #slide_weight, #slide_height {
margin-bottom:14px;
}
#swatch { width: 75px; height: 75px; background-image: none; } #red .ui-slider-range { background: #ef2929; } #red .ui-slider-handle { border-color: #ef2929; }
#green .ui-slider-range { background: #8ae234; } #green .ui-slider-handle { border-color: #8ae234; }
#blue .ui-slider-range { background: #729fcf; } #blue .ui-slider-handle { border-color: #729fcf; }
<h3>Color of Creature (use the color sliders to enter):</h3>
Color (in hexadecimal):<input type="text" class="just_display" name="creature_color" id="color_val" readonly="readonly"/><br /><br /> <div id="swatch" class="ui-widget-content ui-corner-all"></div>
Red:<input type="text" class="just_display" name="creature_color" id="red_val" readonly="readonly"/> <div id="red"></div>
Green:<input type="text" class="just_display" name="creature_color" id="green_val" readonly="readonly"/> <div id="green"></div>
Blue:<input type="text" class="just_display" name="creature_color" id="blue_val" readonly="readonly"/> <div id="blue"></div>
Включите код, выделенный жирным шрифтом, в файлы sightings_end.html и form.css, чтобы подготовить их к по-строению компонента выбора цвета.
form.css
sightings_end.html
Эти стили ис-пользуют цвет ползунка в его оформлении.
Этот идентификатор стиля CSS определя-ет образец, в котором будет отображаться текущий цвет при перемещении ползунка.
Область div для красного ползунка
Область div для зеленого ползунка
Область div для синего ползунка
Область div для образца цвета
Поле input, которое будет содержать шестнадцате-ричное значение цвета
Готово к употреблению
дальше � 429
jquery ui
$( "#red, #green, #blue" ).slider({
orientation: "horizontal",
range: "min",
max: 255,
value: 127,
slide: refreshSwatch,
change: refreshSwatch
});
Диапазон: пользователь может указывать только максимум.
В: А что это за код CSS, прилагаемый к jQuery UI?
О: Одно из преимуществ jQuery UI в том, что разработчики уже написали много слож-ного кода CSS и вам не придется этим за-ниматься. Дополнительная информация об этом коде содержится в файле пакета jQuery UI jquery-ui-1.8.16.custom/css/sunny/jquery-ui-1.8.16.custom.css. За более под-робными описаниями классов CSS обра-щайтесь к документации jQuery UI по адресуhttp://jqueryui.com/docs/Theming/API.
В: Вы сказали, что мы можем создать собственную тему для jQuery UI. Как это сделать?
О: Используйте приложение Theme Roller для jQuery UI. Сначала откройте страницу приложения в браузере: http://jqueryui.com/themeroller/
Щелкните на вкладке Roll your own. Здесь определяются такие параметры конфигура-ции, как шрифты, состояния нажатия кнопок, тени и т. д. Задайте нужные изменения, и лементы пользовательского интерфейса изменяется в соответствии с заданными значениями.Когда тема будет настроена так, как вам нужно, щелкните на кнопке Download Theme. Открывается страница Build Your Download, на которой создается пользовательский пакет jQuery UI. Если вы захотите сохранить свою тему на будущее, просто создайте закладку для страницы Build Your Download.
В: Не пойму, что это за виджеты взаи-модействий. Для чего они нужны?
О: Взаимодействия используются для реализации интерактивных функций, свой-ственных настольным приложениям.Виджеты Draggable обеспечивают возмож-ность перетаскивания элементов.
Виджет Droppable может использоваться в качестве приемника для перетаскиваемых элементов.Виджет Resizable включает возможность масштабирования элемента. Размеры эле-мента изменяются перетаскиванием угла, правой или нижней стороны. Виджеты Selectable обеспечивают поддерж-ку выделения элементов. Посетитель сайта может захватить эти элементы мышью, как при выделении группы файлов на рабочем столе. Виджеты Sortable могут переставляться пользователем в интерактивном режиме.
Возьми в руку карандаш
частоЗадаваемые
вопросы
Следующий фрагмент сценарного кода задает конфигурацию цветовых ползунков
(красного, зеленого и синего). Прочитайте каждую строку и подумайте, что она
может делать, на основании того, что вы уже знаете о jQuery и jQuery UI. Запиши-
те справа свои описания. Если вы не уверены, запишите хотя бы предположения.
Мы заполнили одну строку за вас.
430 глава 10
решение упражнения
Ôóíêöèÿ refreshSwatch
Чтобы завершить построение цветового компонента, необходимо создать функцию JavaScript для обновления образца цвета. Ниже приведена заготовка функции, а также некоторые ключевые вопросы, над которыми следует подумать до написания кода.
Следующий фрагмент сценарного кода задает конфигурацию цветовых
ползунков (красного, зеленого и синего). Прочитайте каждую строку
и подумайте, что она может делать, используя ваши знания о jQuery и
jQuery UI. Запишите справа свои описания. Если вы сомневаетесь, запи-
шите ваши предположения. Ниже приведены наши ответы.
function refreshSwatch() {
var red = ??? var green = ??? var blue = ??? var my_rgb = ??? $( "#swatch" ).???; $( "#red_val" ).val(red );
$( "#blue_val" ).val( blue);
$( "#green_val" ).val( green);
$( "#color_val" ).val(my_rgb);
}
Как перенести текущие значения ползунков в эти переменные?
В этой переменной следует объединить значения RGB для задания цвета образца.
Какой метод jQuery позволит нам задать цвет образца?
Ничего сложного. Достаточ-но просто воспользоваться методом jQuery val, чтобы в полях input отображалось значение ползунков в процессе изменения. Пользователь будет видеть, какое значение уста-новлено на ползунке.
$( "#red, #green, #blue" ).slider({
orientation: "horizontal",
range: "min",
max: 255,
value: 127,
slide: refreshSwatch,
change: refreshSwatch
});
Диапазон: пользователь может указывать только максимум..
Преобразует области div в виджеты slider.Выбирает горизонтальную ориентацию ползунка.
Маркер ползунка устанавливается в середине.
При перемещении ползунка вызывается функция refreshSwatch.Эта функция вызывается при изменении любого значения.
Максимальное значение 255 (ограничения цветовой модели).
Возьми в руку карандаш Решение
дальше � 431
jquery ui
Впрочем, это лишь подсказка для одного из вопросов. Чтобы написать всю функцию, нужно будет немного поработать мозгами.
С получением значений от ползунков все понятно, но как
создать образец цвета? Разве не нужно написать код преобразования шест-надцатеричных веб-цветов?
А ведь и верно! Можно написать функцию преобразования десятичных значений в шестнадцатеричные, а можно просто ис-пользовать десятичные значения.Вспомните, что свойство CSS background-color позволяет задавать цвета в следующем виде:
background-color:rgb(255,0,255)
R G B
w Заполните пропуски в коде функции refreshSwatch.
function refreshSwatch() {
var red =
var green =
var blue =
var my_rgb =
$( "#swatch" ). ;
$( "#red_val" ).val(red );
$( "#blue_val" ).val( blue);
$( "#green_val" ).val( green);
$( "#color_val" ).val(my_rgb);
}
Упражнение
432 глава 10
решение упражнения
function refreshSwatch() {
var red =
var green =
var blue =
var my_rgb =
$( "#swatch" ). ;
$( "#red_val" ).val(red );
$( "#blue_val" ).val( blue);
$( "#green_val" ).val( green);
$( "#color_val" ).val(my_rgb);
}
Заполните пропуски в коде функции refreshSwatch.
Включите в файл my_scripts.js код ползунков и функ-ции refreshSwatch. Также добавьте фрагмент, при-веденный ниже. Он инициирует выполнение функции refreshSwatch при загрузке веб-страницы, чтобы стра-ница загружалась с образцом цвета вместо пустого поля.
$( "#red" ).slider( "value", 127 );
$( "#green" ).slider( "value", 127 );
$( "#blue" ).slider( "value", 127 );
$( "#red" ).slider( "value" );
$( "#blue" ).slider( "value" );
$( "#green" ).slider( "value" );
"rgb(" + red + "," + green + "," + blue + ")";
Объединяя значения RGB в этой переменной…
…мы задаем в CSS образца комбинацию значений трех цветов.
$( "#swatch" ).css( "background-color", my_rgb );
Готово к употреблению
дальше � 433
jquery ui
Откройте файл sightings_end.html в любимом браузере. Проверьте, как работают пол-зунки, с использованием мыши и клавиатуры (клавиши со стрелками влево и вправо должны изменять состояние ползунка на одно приращение).
Теперь пользователи могут вводить данные, перемещая рукоятки ползунков, а криптозоологи смогут получать более качественные данные.
Цветовые ползунки — классная штука! Наши исследования пойдут
намного быстрее.
Тест-драйв
434 глава 10
последняя кнопка
È ïîñëåäíåå...
В: Мы использовали запись RGB для свойства background-color постро-енных нами цветовых ползунков. А если мы захотим создать ползунок, использу-ющий стандартные шестнадцатеричные обозначения цветов?
О: Мы постарались создать самый эле-гантный и простой код цветового ползун-ка. Но если вам нужен ползунок с вводом данных в шестнадцатеричном формате, считайте, что вам повезло. Вы можете ис-пользовать пример кода, размещенный на сайте jQuery UI. Откройте в браузере сле-дующий URL-адрес:
http://jqueryui.com/demos/slider/#colorpicker
Найдите и откройте ссылку View Source. Выделите и скопируйте код HTML, CSS и jQuery в текстовом поле, сохраните его в но-вом документе. Не забудьте включить этот документ в соответствующие файлы CSS и jQuery своего пакета jQuery. Вот и все, у вас появился компонент выбора цвета, исполь-зующий шестнадцатеричные коды цветов.
В: Мне нужно поле формы, которое предлагает возможные условия поиска в процессе ввода. В jQuery UI есть что-нибудь подобное?
О: Да! Одним из новшеств jQuery UI на момент написания книги (август 2011 года) стал виджет Autocomplete, который пред-лагает варианты во время ввода данных в поле формы.
Откуда берутся эти варианты? Вы пере-даете их в массиве JavaScript, через URL-адрес или при помощи функции обратного вызова, которая получает данные с сервера при помощи методов Ajax, описанных в гла-вах 8 и 9. За дополнительной информацией об этом виджете обращайтесь на страницу демонстрационного приложения jQuery UI:
http://jqueryui.com/demos/autocomplete/
В: jQuery UI поддерживает проверку данных форм?
О: Нет. К сожалению, jQuery UI не под-держивает проверку форм, но в jQuery есть модуль расширения, который хорошо справ-ляется с этой задачей. Модуль расширения можно найти по адресу:
http://bassistance.de/jquery-plugins/jquery-plugin-validation/
За дополнительной информацией обра-щайтесь к приложению I, в котором этот модуль расширения рассматривается более подробно.
В нашем списке задач остался последний пункт.
1. Создать календарь для выбора даты наблюдения.
2. Создать более привлекательные кнопки-переключатели для выбора типа существа.
3. Создать ползунки для ввода расстояния, веса и роста существа, широты и долготы места наблюдения.
4. Создать компонент для выбора цвета существа.
5. Создать более симпатичную кнопку отправки данных.
частоЗадаваемые
вопросы
Мы уже работали с кнопками в этой главе, а вы использовали их начиная с главы 1, так что эта задача должна быть простой!
дальше � 435
jquery ui
w
Постойте! Да, мы использова-ли кнопки из главы 1, но ведь кнопка jQuery UI и элемент
HTML — не одно и то же!
Напишите одну строку кода, которую следует добавить в файл my_scripts.js для преоб-разования «классической» кнопки в кнопку jQuery UI, соответствующей теме оформления.
Верное замечание.Мы использовали метод jQuery click и метод jQuery UI button, но не занимались выбором элементов форм, например кнопок от-правки данных. Ниже приведена краткая справка по выбору таких элементов.
� $(":input") = Выбор всех элементов input
� $(":text") = Выбор всех элементов типа text
� $(":radio") = Выбор всех элементов типа radio
� $(":checkbox") = Выбор всех элементов типа checkbox
� $(":submit") = Выбор всех элементов типа submit
� $(":reset") = Выбор всех элементов типа reset
� $(":checked") = Выбор всех полей input в состоянии checked
� $(":selected") = Выбор всех полей input в состоянии selected
� $(":enabled") = Выбор всех незаблокированных полей input
� $(":disabled") = Выбор всех заблокированных полей input
� $(":password") = Выбор всех полей input, предназначенных для ввода пароля
Упражнение
ÊËÞ×ÅÂÛÅ ÌÎÌÅÍÒÛ
436 глава 10
решение упражнения
$( "button:submit" ).button(); ;
Не забудьте включить эту строку в файл my_scripts.js и протестировать ее, открыв файл sightings_end.html в своем любимом браузере.
Мы очень довольны вашей работой, так что непременно обратимся к вам за помощью
в следующей главе.
Тоже мне, удружили!Теперь не будет
ни минуты покоя!
дальше � 437
jquery ui
Форма отлично смотрится, но на данный момент она не отправляет никакие данные. Впрочем, вы уже узнали все необходимое в главе 9. Пора подумать, как сделать стильную форму полностью функциональной. Папка end в архиве кода этой главы содержит все файлы, необходимые для работы: sightings.html, service.php и sightings.sql. Конечно, вам придется проделать часть работы по на-стройке самостоятельно, но ведь в этом и заключается задача веб-разработчика, не так ли? Мы включили методы Ajax и JSON, описанные в главе 9, чтобы построенная вами форма могла отправлять данные.
Всю необходимую подготовку вы должны провести самостоятельно (т. е. запустить сценарий sightings.sql или же создать базу данных с полями из сценария самостоятельно и включить ме-тоды Ajax и JSON в файл my_scripts.js). Также до перехода к главе 11 в базе данных необходимо создать несколько записей. Если вам понадобится освежить в памяти информацию о MySQL, PHP и AJAX, обращайтесь к главам 8 и 9.
Дополнительный материал
У этого упражнения нет решения. Если у вас возникнут проблемы, вы всегда можете зайти на форум книги по адресу www.headfirstlabs.com и пообщаться с авторами или другими читателями.
Упражнение
438 глава 10
ваш инструментарий jquery
jQuery UI
Официальная библиотека
jQuery с тремя основными
типами расширений для базо-
вой функциональности jQuery:
эффекты, взаимодействия
и виджеты.
Âàø èíñòðóìåíòàðèé jQuery
Глава 10 осталась позади. Ваш творческий потенциал дополнился навыками использования jQuery UI.
Виджет
Компонент, расширяющий функ-
циональность веб-приложения.
Экономит время при програм-
мировании, упрощает создание
удобных, практичных элементов
пользовательского интерфейса.
Виджет button
Предоставляет метод button
для создания более привлекатель-
ных элементов форм — кнопок
отправки данных, переключате-
лей и флажков.
Виджет datepicker
Метод datepicker приказывает
интерпретатору JS построить
календарь «на ходу»
— вместе
со всем кодом HTML, CSS и встро-
енной интерактивностью.
Поддерживает большое количе-
ство настраиваемых параметров.
ПолзункиЭлементы пользовательского интерфейса, которыми можно управлять как мышью, так и клавиатурой; ограничивают набор
вводимых данных.Поддерживают пять обработ-чиков событий, которые могут использоваться для связывания ползунка с полем input формы:
create, start, slide, change и stop.
ГЛА
ВА 10
Интересно, что мне подарят в этом году? Надеюсь, новый API...
jQuery и API11
Объекты, сплошные объекты
Даже самый талантливый разработчик не сможет сделать всю работу в одиночку... Мы уже видели, как включать расширения jQuery (такие как jQuery UI или вкладки) для повышения уровня функциональности приложения. Чтобы поднять наше приложение на следующий уровень — ис-пользовать Интернет и информацию из крупных информационных систем типа Google, Twitter или Yahoo! — понадобится... нечто большее. Эти компании предоставляют вам программные интерфейсы (API, Application Programming Interface). В этой главе мы рассмотрим основы работы с API, а также исполь-зуем очень распространенный сервис Google Maps API.
440 глава 11
снова с криптидами
Ãäå âèäåëè ñíåæíîãî ÷åëîâåêà?
Доктор Паттерсби и доктор Гимли хотят добавить на свой сайт новые классные возможности. Как думаете, вы справитесь с этой задачей?
От: Доктор Гимли [[email protected]]
Тема: Обновления на сайте
Привет,Спасибо вам за то, что помогли сделать наш сайт более удобным и упростили
сбор данных о наблюдениях. Трафик заметно вырос, и мы едва справляемся
с обработкой всех собранных данных.
У нас есть несколько пожеланий для того, чтобы сделать информацию более
доступной для широких масс. Многие люди интересуются данными наблюдений,
и мы бы хотели предоставить им возможность собранных данных.
Вот что нам нужно:
1) нужно предоставить пользователю возможность просмотреть данные отдельного
наблюдения и всю информацию, связанную с ним. Наряду с информацией
о существе нам хотелось бы видеть информацию на карте Google;
2) выбирая маркер на карте Google, пользователь получает дополнительную
информацию о наблюдении;
3) нам хотелось бы, чтобы при выборе типа существа из списка отображалась
информация обо всех существах, связанных с выбранным типом в нашей
базе данных. При этом информация обо всех существах должна отображаться
на карте Google, чтобы мы могли найти места частых наблюдений для более
внимательного изучения. Можно ли сделать так, чтобы все эти точки тоже
реагировали на щелчки для получения дополнительной информации (как
и пункты списка существ)?
Надеюсь, мы хотим не слишком многого, ведь вся информация уже хранится в базе
данных?Ждем ответа!
--Доктор Гимли и доктор Паттерсби cryptozoologists.org
дальше � 441
jquery и api
Джо: Ты говоришь о карте Google, которую нам предсто-ит создать?
Фрэнк: Ага. Тривиально, в общем.
Джим: Тривиально? Они хотят полноценную карту Google!
Фрэнк: Угу.
Джим: С несколькими маркерами на карте — по одному для каждого криптида. И эти маркеры должны реагиро-вать на щелчки выводом дополнительной информации.
Фрэнк: Да! И я, кажется, знаю, как это делать.
Джим: А еще щелчки в списке должны взаимодейство-вать с маркерами — на карте должны появляться времен-ные окна с дополнительной информацией.
Фрэнк: Это уже сложнее... Я пока не знаю, как это сде-лать.
Джо: Беспокоиться не о чем. Разработчики Google Maps уже предоставили API, с которым мы все сделаем.
Джим: Чего предоставили?
Фрэнк: API... Программный интерфейс, короче. Так, компании типа Google, Netflix и Yahoo! дают нам возмож-ность использовать свой сервис на наших сайтах.
Джим: Это хорошо, конечно, но есть ли в нем временные окна и все остальное, что нужно выводить на карте?
Джо: Должно быть. Наверное, нам стоит поближе позна-комиться с интерфейсом Google Maps API и понять, как он работает.
Не вижу препятствий. Собственно, они хотят не так уж много.
Джим ФрэнкДжо
442 глава 11
изучаем API
Google Maps API
Использование любого API на вашем сайте начинается с поиска докумен-тации и примеров кода в Интернете. Мы загрузили этот пример по адресу http://code.google.com/apis/maps.
var map;
function initialize() { var myLatlng = new google.maps.LatLng(40.720721,-74.005966); var myOptions = { zoom: 13, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); google.maps.event.addListener(map, 'zoom_changed', function() {
setTimeout(moveToNewYork, 3000);
}); var marker = new google.maps.Marker({
position: myLatlng, map: map, title:"Hello World!"
});
google.maps.event.addListener(marker, 'click', function() {
map.setZoom(8);
});
} function moveToNewYork() {
var NewYork = new google.maps.LatLng(45.526585, -122.642612); map.setCenter(NewYork);
}Так, некоторые переменные и функции выглядят знакомо,
а все остальное?
Это код Google.Но все не так страшно, как может показаться. Давайте разберемся, что же происходит в этом коде.
дальше � 443
jquery и api
 API èñïîëüçóþòñÿ îáúåêòû
var map;
var myLatlng = new google.maps.LatLng(40.720721,-74.005966);
var myOptions = {
zoom: 13,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
google.maps.event.addListener(map, 'zoom_changed', function() {
setTimeout(moveToNewYork, 3000);
});
Объявляем переменные. Переменной присваивается новый объект Google LatLng.
Передаем широту и долготу в парамет-рах объекта.
Размещаем карту в элементе map_canvas.
Создаем массив для хранения параметров карты.
Перемен-ной map присва-ивается новый объект Google Maps.
Добавляем слушателя события к карте Google.
var marker = new google.maps.Marker({
position: myLatlng,
map: map,
title:"Hello World!"
});
function moveToNewYork() {
var NewYork = new google.maps.LatLng(45.526585, -122.642612);
map.setCenter(NewYork);
}
Объявляем переменную для объекта Marker.
Передаем нуж-ные значения в параметрах.
Объект LatLng, объявленный ранее.
Объект Map, объявленный ранее.
Объявляем функцию для вызова кода Google.
Выбираем централь-ную точку карты.
Создаем другой объект LatLng.
В главе 6 мы создавали объекты JavaScript. Используя свойства и методы этих объектов, мы орга-низуем хранение и обработку информации так, как считаем нужным. Многие компании — Google, Netflix, Microsoft и Yahoo! — тоже создают объекты для работы со своими данными через API. Если вы успели забыть, что такое объекты и как они работают, вернитесь к главе 6 и перечитайте ее.
444 глава 11
почему именно объекты?
Потому что это ускоряет работу.Из главы 6 вы знаете, что информацию удобно хранить в объектах. Объекты ис-пользуются для хранения переменных, относящихся к одной сущности. Фактически API — это набор конструкторов объектов, которые позволяют создавать собствен-ные экземпляры объектов, определенных другими разработчиками. Если есть эк-земпляр объекта, вы можете использовать все его свойства и методы в коде!
Внедрить в приложение поддержку географических карт достаточно сложно; имен-но поэтому Google использует объекты в своем API. Это позволяет разработчикам создавать объекты с множеством разных методов и свойств, необходимых для по-строения карты.
Объект карты содержит свойства zoom, center и mapTypeId, а также много других свойств, в предыдущем примере не использовавшихся. Объект карты также поддер-живает многочисленные методы, например setCenter.
<!DOCTYPE html>
<html>
<head>
<title>View Cryptid Sightings</title>
<link type="text/css" href="style/form.css" rel="stylesheet"/>
<link type="text/css" href="jquery-ui-1.8.16.custom/css/sunny/jquery-ui-1.8.16.custom.css" />
</head>
<body>
< div class="ui-widget-header ui-corner-top form_pad">
<h2>View Cryptid Sightings</h2>
</div>
<div class="ui-widget-content form_pad">
<div id="map_canvas"></div>
</div>
<script src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script src="scripts/jquery-1.6.2.min.js"></script>
<script src="scripts/maps.js"></script>
</body>
</html>
Задание!
Включаем Google Maps API.
Включаем библиотеку jQuery.
Включаем файл maps.js.
Создаем область для размещения карты.
display_one.html
Создайте страницу display_one.html и сохра-ните ее в папке проекта этой главы.
Значит, в APIs все делается при помощи объектов? И почему мы должны исполь-
зовать объекты, созданные кем-то другим?
дальше � 445
jquery и api
Âêëþ÷åíèå êàðò Google â ñòðàíèöó
Сначала скопируйте все необходимые файлы, которые были созданы в конце предыдущей главы. Наша работа продолжится с того момента, на котором она прервалась ранее. В этом коде (вместе с новым файлом display_one.html) присутствуют два важных изменения.
Расставьте магниты так, чтобы у вас получился код функции initialize. Эта функция долж-
на создавать новый экземпляр объекта Google Maps map с использованием параметров,
определенных в коде. Объект map размещается в элементе map_canvas страницы. Также
включите в существующий файл form.css определения стилей контейнера карты.
Область div с идентификатором map_canvas.
Код Google Maps API, добавленный с включением фрагмента <script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=false"></script>.
Чтобы создать карту Google на странице, необходимо создать файл maps.js и включить в него функцию с вызовом кода API.
$(document).ready. ____________{
var _____________
function ______________{
var latlng = new google.maps.LatLng. ____________________;
var mapOpts = {
_____________: 13,
center: latlng,
mapTypeId: google.maps.MapTypeId._____________
};
map = ___________google.maps.Map(document.getElementById(_____________), mapOpts);
}
initialize();
});
#map_canvas {
_____________ :left;
height: 450px;
width: ____________
}
form.css
maps.js(45.519098,-122.672138) initialize()
"map_canvas" (function()
zoom
new
HYBRID
map; float
450px;
Развлечения с магнитами
446 глава 11
решение упражнения
Расставьте магниты так, чтобы получился код функции initialize. Эта функция должна
создавать новый экземпляр объекта Google Maps map с параметрами, определенными в
коде. Объект map размещается в элементе map_canvas страницы. Также включите в суще-
ствующий файл form.css определения стилей контейнера карты.
В: А что это за объект LatLng и свойство mapOpts?
О: За дополнительной информацией об объ-ектах, методах и прочих аспектах API обращай-тесь по адресу http://code.google.com/apis/maps/documentation/javascript/reference.html. На сайте имеются примеры кода и более подробная ин-формация о разных объектах и методах, которые понадобятся вам при программировании.
В: Google Maps — это единственный способ создания карт?
О: Конечно, нет! Однако это самый популяр-ный способ, поэтому мы здесь им и воспользова-лись. Другие компании (такие как Yahoo!, Microsoft, MapQuest и OpenLayers) тоже предлагают свои картографические API.
$(document).ready. ____________{
var _______
function ______________{
var latlng = new google.maps.LatLng. --- ____________________;
var mapOpts = {
______: 13,
center: latlng,
mapTypeId: google.maps.MapTypeId._________
};
map = ______google.maps.Map(document.getElementById(______________), mapOpts);
}
initialize();
});
#map_canvas {
_______ :left;
height: 450px;
width: ________
}
form.css
maps.js
--- ____________________;(45.519098,-122.672138)
______________{
latlng = new goog
______________initialize()
______________),"map_canvas"
. ____________{(function()
______:
center:
zoom
______gonew
_________HYBRID
r _____
nction
___
ini
map;
_______
height: float
p ;
________450px;
Развлечения с магнитами. Решение
частоЗадаваемые
вопросы
дальше � 447
jquery и api
Включите в файл maps.js функцию initialize, собранную из магнитов. Также убедитесь в том, что файл maps.js включен в display_one.html. Затем откройте файл display_one.html в браузере. Весь код должен выполняться через веб-сервер, поэтому URL-адрес должен начинаться с префикса http://, а не file://.
Отлично, разместить карту на страни-це было несложно... Но на ней нет никаких
данных криптидов. Их нужно загрузить из базы данных, верно?
Точно.В главе 9 вы научились читать информацию из базы данных MySQL с использованием кода jQuery, Ajax, JSON, PHP и MySQL. Хотя список задействованных технологий получается довольно длинным, в результате мы получаем именно то, что нужно. Давай-те посмотрим, как использовать эти технологии на этот раз.
Тест-драйв
448 глава 11
старые знакомые
×òåíèå äàííûõ JSON ñðåäñòâàìè SQL è PHP
В главе 9 было показано, как команда SQL select извлекает нужную информацию из базы данных, чтобы файл PHP мог преобразовать ее в формат JSON и вернуть странице с использованием Ajax.
Вы также научились использовать Ajax для получения от файла PHP информации, закодированной в формате JSON. С возвращением данных JSON страницей PHP все было просто — функция json_encode получала массив и возвращала данные JSON, с которыми можно было работать средствами jQuery.
SELECT COLUMN_NAME1, COLUMN_NAME2 FROM TABLE_NAME order by COLUMN_NAME1 ASC
$my_array = array();
array_push($my_array, array('my_key' => 'my_val'));
echo json_encode($my_array);
Весь код PHP и SQL для этой главы мы написали за вас. Скопируйте базу данных MySQL из главы 10 и двигайтесь дальше! Остальной код SQL и PHP находится в архиве кода главы; выполните его на своем сервере. Весь код PHP и SQL, объединенный в один файл, можно за-грузить по адресу http://thinkjquery.com/chapter11/end/service.zip.
Сама база данных часто
хранится в файлах на
жестком диске, но это
необязательно.
Веб-сервер
Сервер баз данных
Серверный компьютер
Клиентский браузер
База данных MySQL
Веб-сервер обрабатыва-ет запросы веб-страниц, выполняет сценарии PHP и возвращает данные в формате HTML.
Данные
<? php
>?
JSON
дальше � 449
jquery и api
function getAllSightings(){
$.getJSON("service.php?action=getAllSightings",___________________ {
if (______________length > 0) {
$("#sight_list")___________________;
___________________(json.sightings,function() {
var info = 'Date: ' + this['date'] + ', Type: ' + this['type'];
var $li = $("<li />");
___________________
$li.addClass(___________________);
$li.attr('id', this['id']) ;
$li.appendTo(___________________);
});
}
});
}
#sight_nav{
float:left;
}
ul#sight_list{
width:150px;
padding:0px;
margin:0px;
}
li.sightings {
padding:4px;
background:#7B7382;
border:1px #000 solid;
color:#fff;
___________________
}
___________________
background:#eee;
color:#000;
}
form.css
maps.js
Расставьте магниты в коде файлов display_one.html, forms.css и maps.js так, чтобы обеспечить
загрузку данных в формате JSON и их отображение на экране. Добавьте элементы div и ul
для хранения данных, немного кода CSS для стилевого оформления списка, а также функ-
цию получения данных (через JSON) для включения криптидов в список.
list-style:none;
li.sightings:hover {
"map_canvas"
"sight_list"function(json)
json.sightings.
.empty()
$.each
$li.html(info);
"sightings"
"#sight_list"
<div class="ui-widget-content form_pad">
<div id= ___________________></div>
<div id="sight_nav">
<ul id= ___________________>
</ul>
</div>
</div>
display_one.html
Развлечения с магнитами: jQuery, HTML и CSS
450 глава 11
решение упражнения
<div class="ui-widget-content form_pad">
<div id= _______________></div>
<div id="sight_nav">
<ul id=_________________>
</ul>
</div>
</div>
display_one.html
function getAllSightings(){
$.getJSON("service.php?action= getAllSightings",_________________{
if (_____________ .length > 0) {
$("#sight_list") ________;
_______(json.sightings,function() {
var info = 'Date: ' + this['date'] + ', Type: ' + this['type'];
var $li = $("<li />");
______________
$li.addClass(____________);
$li.attr('id', this['id']) ;
$li.appendTo(_____________);
});
}
});
}
#sight_nav{
float:left;
}
ul#sight_list{
width:150px;
padding:0px;
margin:0px;
}
li.sightings {
padding:4px;
background:#7B7382;
border:1px #000 solid;
color:#fff;
________________
}
__________________
background:#eee;
color:#000;
}
form.css
maps.js
Расставьте магниты в файлах display_one.html, forms.css и maps.js так, чтобы загружать дан-
ные в формате JSON и отображать их на экране. Добавьте элементы div и ul для хранения
данных, немного кода CSS для стилевого оформления списка, а также функцию получения
данных (через JSON) для включения криптидов в список.
________________list-style:none;
__________________
background:#eee;
li.sightings:hover {
g
= _______________><
="sight nav">
"map_canvas"
g t_ a
=_________________>
ight nav >
"sight_list"
_________________{function(json)
(_____________ .le
("#sight list")
_____________ ljson.sightings. g
) ________;
ghtings,fun
) .empty()
_______(j
var in$.each
$li.addClass($li.html(info);
____________)
this['id'])
;"sightings"
(_____________);"#sight_list"
Развлечения с магнитами: jQuery, HTML и CSS. Решение
дальше � 451
jquery и api
Включите в файл maps.js только что созданную функцию getAllSightings. Вклю-чите ее вызов в конец функции initialize. Откройте файл display_one.html в бра-узере. Предполагается, что в главе 10 вы уже включили информацию о нескольких существах в базу данных; если вы еще этого не сделали, обязательно сделайте сейчас. Помните, что весь код должен выполняться через веб-сервер; соответственно URL-адрес должен начинаться с префикса http://, а не file://.
Все это хорошо, конечно... Только на карте по-прежнему
ничего не отображается.
Точно. Нужно нанести данные криптидов на карту. В интерфейса Google Maps для этой цели существует очень простой метод. Давайте посмотрим, как он работает.
Тест-драйв
452 глава 11
маркеры на карте
Òî÷êè íà êàðòå — ìàðêåðû
Естественно, Google поддерживает возможность нанесения точек на карту, только они называются не точками, а маркерами (marker). Маркеры представляют собой объекты (как и все остальное в Google Maps API); они также обладают методами и свойствами, через которые с ними выполняются необходи-мые операции.
var myLatLng = new google.maps.LatLng(45.519098,-122.672138);
var my_marker = new google.maps.Marker({
position: myLatlng,
map: map,
title:"Hi! I’m a marker. Seen me around before?"
});
Здесь мы задаем позицию маркера,
карту, на которой он размеща-
ется, и название маркера.
Передаем аргументы для задания
свойств объекта my_marker.
Определенный ранее объект LatLng передается в параметре.
Определяем объект с именем my_marker
как экземпляр объекта маркера Google.
Готовый объект кар-ты. Вы уже видели, как он работает.
Вызываем конструктор объекта Google Marker.
Определяем новый объект LatLng из Google Maps API.
Передаем фактические значения широты и дол-готы в параметрах.
Привет! Я маркер. Раз познако-миться. Мы ведь уже встречались
на картах Google, не так ли?
дальше � 453
jquery и api
function getAllSightings(){
$.getJSON("service.php?action=getAllSightings", function(json) {
if (json.sightings.length > 0) {
$("#sight_list").empty();
$.each(json.sightings,function() {
var info = 'Date: ' + this['date'] + ', Type: ' + this['type'];
var $li = $("<li />");
$li.html(info);
$li.addClass("sightings");
$li.attr('id', this['id']) ;
$li.click(function(){
______________________ this['id'] );
});
$li.appendTo("#sight_list");
});
}
});
}
function getSingleSighting(______________________){
$.getJSON("service.php?action=getSingleSighting&id="+id, function(json) {
if (json.sightings.length > 0) {
__________________________________
var loc = new google.maps.LatLng(this['lat'], this['long']);
var my_marker = new google.maps______________________({
______________________loc,
map: map,
title:this['type']
});
_________________setCenter(loc, 20);
});
}
});
} maps.js
Возьми в руку карандашВключите в функцию getAllSightings добавление слушателя события click к элементу списка
до того, как он будет включен в список. Событие click должно вызывать getSingleSighting
с параметром (идентификатор наблюдения, на котором щелкнул пользователь). Новая функция
загрузит информацию о наблюдении и добавит его на карту в виде маркера.
454 глава 11
решение упражнения
После включения всего кода элементы списка реагируют на щелчки,
они загружают данные о криптиде, на котором щелкнул пользова-
тель, и размещают их на карте.
function getAllSightings(){
$.getJSON("service.php?action=getAllSightings", function(json) {
if (json.sightings.length > 0) {
$("#sight_list").empty();
$.each(json.sightings,function() {
var info = 'Date: ' + this['date'] + ', Type: ' + this['type'];
var $li = $("<li />");
$li.html(info);
$li.addClass("sightings");
$li.attr('id', this['id']) ;
$li.click(function(){
this['id'] );
});
$li.appendTo("#sight_list");
});
}
});
}
function getSingleSighting( ){
$.getJSON("service.php?action=getSingleSighting&id="+id, function(json) {
if (json.sightings.length > 0) {
var loc = new google.maps.LatLng(this['lat'], this['long']);
var my_marker = new google.maps ({
loc,
map: map,
title:this['type']
});
setCenter(loc, 20);
});
}
});
} maps.js
getSingleSighting(
id
$..each(json..sightings,function() {
..Markerposition:
map.
Возьми в руку карандаш Решение
дальше � 455
jquery и api
Включите в файл maps.js только что созданные функции getAllSightings и getSingleSighting. Откройте файл display_one.html в браузере (как и прежде, с использованием префикса http://).
Ого! Да, это впечатляет. А как насчет нашей второй просьбы? Помните, об одно-
временном отображении данных нескольких наблюдений?
С первыми двумя требованиями мы уже разобрались. Пора заняться последним требованием в списке криптозоологов.
ддальше � 455
р р
3) Нам хотелось бы, чтобы при выборе типа существа из списка отображалась
информация обо всех существах, связанных с выбранным типом в нашей базе
данных. При этом информация о существах должна отображаться на карте
Google, чтобы найти места частых наблюдений для внимательного изучения.
Можно ли сделать так, чтобы все эти точки тоже реагировали на щелчки для
получения дополнительной информации (как и пункты списка существ)?
Тест-драйв
456 глава 11
готовый код раскрывающегося списка существ
Создайте новую страницу с именем display_type.html и сохраните ее в одном каталоге с другими файлами HTML этого проекта. Новый файл будет отображать список доступных типов существ. Все суще-ства выбранного типа отображаются на карте. По структуре и сти-лю новая страница почти не отличается от старой, если не считать добавления элемента select с идентификатором ddlTypes.
Ñïèñîê çàäà÷ äëÿ îòîáðàæåíèÿ íåñêîëüêèõ ñóùåñòâ
Вот что нужно сделать для реализации последнего требования.
1. Создать раскрывающий список типов существ (информация из базы данных).
2. При изменении состояния списка получить соответствующий список существ.
3. Вывести информацию обо всех существах из базы данных, в списке и на карте.
4. И список, и маркеры на карте должны реагировать на щелчки, чтобы на карте отображалась дополнительная информация.
<!DOCTYPE html> <html> <head> <title>View Cryptid Sightings</title> <link type="text/css" href="style/form.css" rel="stylesheet" /> <link type="text/css" href="jquery-ui-1.8.16.custom/css/sunny/jquery-ui-1.8.16.custom.css"/> </head> <body> <div class="ui-widget-header ui-corner-top form_pad"> <h2>View Cryptid Sightings</h2> </div> <div class="ui-widget-content form_pad"> <div id="map_canvas"></div> <div id="sight_nav"> <select id="ddlTypes"> <option value="">-- Please Select --</option> </select> <ul id="sight_list"></ul> </div> </div> <script src="http://maps.google.com/maps/api/js?sensor=false"></script> <script src="scripts/jquery-1.6.2.min.js"></script> <script src="scripts/maps.js"></script> </body></html>
display_type.html
Добавляем раскрывающийся список,
заполняемый типами существ.
Включаем Google Maps API.
Включаем библиотеку jQuery.Включаем файл maps.js.
Готово к употреблению
дальше � 457
jquery и api
Расставьте магниты так, чтобы заполнить пропуски в функции getAllTypes, которая вызывает файл
service.php (включенный в архив кода этой главы) для получения списка разных типов существ
в базе данных. Полученные типы включаются в раскрывающийся список с идентификатором
ddlTypes. Для раскрывающегося списка определяется слушатель события change, который вы-
водит выбранное значение. Поскольку файл maps.js используется для двух файлов HTML, в функ-
цию initialize включается проверка существования раскрывающегося списка. Если список
существует, то вызывается функция getAllTypes, а если нет — функция getAllSightings.
function initialize(){
.
.
map = new google.maps.Map(document.getElementById(________________), mapOpts);
if ( $('#ddlTypes').length ) {
___________________
}else{
___________________
}
}
function getAllTypes(){
$.getJSON("service.php?action=getSightingsTypes", function(json_types) {
if (___________________creature_types.length > 0) {
$.each(json_types.creature_types,___________________
var info = this['type'];
var $li = ___________________
$li.html(info);
$li___________________("#ddlTypes");
});
}
});
}
___________________change(function() {
if($(this).val() != ""){
alert( $(this).val() );
}
});
maps.js
$("<option />");
function() {
getAllTypes();
json_types.
getAllSightings();
"map_canvas"
$('#ddlTypes').
.appendTo
Развлечения с магнитами
458 глава 11
решение упражнения
function initialize(){
.
.
map = new google.maps.Map(document.getElementById(_____________), mapOpts);
if ( $('#ddlTypes').length ) {
______________
}else{
_________________
}
}
function getAllTypes(){
$.getJSON("service.php?action=getSightingsTypes", function(json_types) {
if (___________ creature_types.length > 0) {
$.each(json_types.creature_types,_____________
var info = this['type'];
var $li = ________________
$li.html(info);
$li_________ ("#ddlTypes");
});
}
});
}
_______________ change(function() {
if($(this).val() != ""){
alert( $(this).val() );
}
});
maps.js
Проверка существования элемента по свойству length.
Добавляем слушателя для события change рас-крывающегося списка.
Присоединяем новый пункт к раскрывающемуся списку.
Задаем текст пункта раскрыва-ющегося списка.
Получение типов из базы данных с использованием JSON и PHP.
Значение выбранного пункта списка.
Теперь в нашем приложении имеется раскрывающийся список, связанный с картой Google,
и функция получения информации (в формате JSON) о типах существ, а приложение выводит
сообщение о выбранном типе существа.
yp
________________
info);
$("<option />");
) {
,_____________function() {
______________
else{
getAllTypes();
(___________ cr
.each(json typ
json_types.
_________________getAllSightings();
_____________),"map_canvas"
_______________ ch
if($(this).val(
р$('#ddlTypes').
i.html(i
i_________ ("
info);
.appendTo
Развлечения с магнитами. Решение
дальше � 459
jquery и api
Включите в файл maps.js функцию getAllTypes и слушателя события change раскры-вающегося списка. Также внесите необходимые изменения в функцию initialize. Наконец, откройте файл display_type.html (снова с использованием префикса http://).
1. Создать раскрывающийся список типов существ (информация читается из базы данных).
2. При изменении состояния раскрывающегося списка получить из базы список существ выбран-ного типа.
3. Вывести информацию обо всех существах, полученную из базы данных, в списке и на карте.
4. И список, и маркеры на карте должны реагировать на щелчки, чтобы на карте отобража-лась дополнительная информация.
Работа идет полным ходом, карта готова в кратчайшие сроки! Пора вычеркнуть пару требований из списка.
Тест-драйв
460 глава 11
не так быстро
Эй, не так быстро! Когда я выбираю один из пунктов раскрывающегося списка, никакие
существа не отображаются. Я вижу только окно сообщения! По-моему, второй пункт
еще не готов.
var markersArray = [];
var bounds = new google.maps________________;
function getSightingsByType(type){
$.getJSON("service.php?action=getSightingsByType&type="+type, function(json) {
if (_________sightings.length > 0) {
$('#sight_list').empty();
$.each(json.sightings,function() {
var loc = new google.maps______________(this['lat'], this['long']);
var opts = {
map: map,
position:________________
};
А ведь и верно!
Нужно изменить наш код так, чтобы при изменении состо-яния раскрывающегося списка информация загружалась из базы данных (вместо простого вывода типа существа в окне сообщения).
И тогда этот элемент списка может будет вычеркнуть. Но раз уж мы занялись этой задачей, заодно выполним тре-тий пункт из списка задач. Закатайте рукава, нам придется изрядно повозиться, чтобы собрать все воедино.
Длинные упражнения Заполните пропуски в коде функции getSightingsByType. Этой функции
передается один параметр: тип существа, по которому просматривается информа-ция. Функция получает данные в формате JSON, перебирает возвращенных существ (если они есть) и добавляет на карту маркеры. Создайте еще две глобальные переменные: массив с именем markerArray, и новый объект Google Maps LatLngBounds с именем bounds, и функцию, которая удаляет предыдущие маркеры перед добавлением новых, когда выбор в списке меняется.
дальше � 461
jquery и api
var marker = new google.maps________________(opts);
markersArray.push(________________);
var $li = $("<li />");
$li.html('Date: ' + this['date'] + ', Type: ' + this['type']);
$li________________("sightings");
$li.appendTo("#sight_list");
bounds.extend(loc);
});
map.fitBounds(bounds);
}
});
}
$('#ddlTypes').change(function() {
if($(this).val() != ""){
clearOverlays();
________________( $(this).val() );
}
});
function ________________ {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(null);
}
markersArray.length = 0;
bounds = null;
bounds = new________________LatLngBounds();
}
}
maps.js
462 глава 11
решение длинного упражнения
После добавления двух новых глобальных переменных и вызовов функций Google Maps приложение добавляет и удаляет маркеры на карте при изменении выбора в списке. Маркеры, добавленные на карту, включаются в массив markerArray и использу-ются для расширения границ карты bounds. Таким образом, карта масштабируется по точкам при помощи функции fitBounds. Функция getSightingsByType, теперь вызываемая при любом изменении выбора в раскрывающемся списке, добавляет маркеры на карту и включает существо в список на странице.
var markersArray = [];
var bounds = new google.maps ;
function getSightingsByType(type){
$.getJSON("service.php?action=getSightingsByType&type="+type, function(json) {
if ( sightings.length > 0) {
$('#sight_list').empty();
$.each(json.sightings,function() {
var loc = new google.maps (this['lat'], this['long']);
var opts = {
map: map,
position:
};
var marker = new google.maps (opts);
markersArray.push( );
var $li = $("<li />");
$li.html('Date: ' + this['date'] + ', Type: ' + this['type']);
$li ("sightings");
$li.appendTo("#sight_list");
bounds.extend(loc);
});
map.fitBounds(bounds);
}
});
}
..LatLngBounds()(
..addClass
marker
loc
..LatLng
json.
Новый объект LatLngBounds.
Получаем данные в формате JSON.
Создаем новый объект Marker
для каждой точки на карте.
Включаем теку-щие координаты в объект bounds.
Выбираем масштаб по границам объекта bounds, чтобы на карте были видны все точки наблюдений.
..Marker
Решение длинных упражнений
дальше � 463
jquery и api
Мы включили функцию clearOverlays, которая удаляет ра-
нее добавленные маркеры перед добавлением новых. На картах
Google все дополнительные элементы, размещаемые на базовой
карте, называются слоями (overlays); это могут быть объекты типа
Marker, Line, Polyline, Polygon и других типов.
$('#ddlTypes').change(function() {
if($(this).val() != ""){
clearOverlays();
( $(this).val() );
}
});
function {
if (markersArray) {
for (i in markersArray) {
markersArray[i].setMap(null);
}
markersArray.length = 0;
bounds = null;
bounds = new LatLngBounds();
}
}
maps.js
..google..maps.
clearOverlays()
Перед добавлением мар-керов удаляем с карты все старые маркеры.
Значение раскрывающегося списка передается в параметре функции.
Удаляем объект Marker с карты.
Также сбрасываем переменную bounds.
getSightingsByType
Для любознательных
464 глава 11
тест-драйв
Включите только что созданный код в файл maps.js. Откройте файл display_type.html в браузере и выберите один из типов существ в списке.
Осталось совсем немного… Всего один пункт!
1. Создать раскрывающийся список типов существ (информация читается из базы данных).
2. При изменении состояния раскрывающегося списка получить из базы список существ выбран-ного типа.
3. Вывести информацию обо всех существах, полученную из базы данных, в списке и на карте.
4. И список, и маркеры на карте должны реагировать на щелчки, чтобы на карте отобража-лась дополнительная информация.
Тест-драйв
дальше � 465
jquery и api
В: Значит, я могу бесплатно использо-вать Maps API на своем сайте?
О: Да! Google бесплатно предоставляет API всем (для использования в личных или коммерческих целях), при условии выполне-ния пользовательского соглашения.
В: Но я не знаю, выполняю я эти усло-вия или нет. Где можно ознакомиться с пользовательским соглашением?
О: Полный текст пользовательско-го соглашения находится по адресу http://www.google.com/apis/maps/terms.
В: Google Maps API работает с картами всего мира?
О: Осталось совсем немного стран, на которые сервис Google Maps не распро-страняется. Список можно найти на сайте Google Maps API list.
В: Могу ли я пользоваться этими кар-тами на мобильных устройствах?
О: Да, можете. На момент издания кни-ги вышла 3 версия Google Maps API. Она разрабатывалась с учетом мобильных устройств, для браузеров с поддержкой JavaScript.
В: Но я бы хотел написать специаль-ное приложение. Google Maps API мне подойдет?
О: Если вы пишете на платформе Android или iPhone — подойдет. Google предостав-ляет для этих платформ библиотеки, кото-рые следует включить в приложение. На других мобильных платформах вам при-дется использовать API так же, как на сайте.
В: Полная версия Google Maps позво-ляет находить маршруты. Способен ли на это данный API?
О: Нет, это невозможно. Компания Google разработала другой API — Google Directions API, который позволяет искать маршруты.
В: А как насчет поиска мест на карте по адресу?
О: На профессиональном жаргоне это называется геокодированием. У Google для этого есть специальный Geocoding API. Все упоминавшиеся интерфейсы входят в семейство Google Maps API. К счастью, все данные от Google поставляются в формате JSON, с которым вы уже умеете работать.
В: Какие еще API входят в семейство Google Maps API?
О: Directions API и Geocoding API отно-сятся к подразделу, называемому Maps API Web Service. Также в этот подраздел входят интерфейсы Distance API, Elevation API и Places API.
В: А есть и другие?
О: Да. Есть Static Maps API для браузе-ров, не имеющих полноценной поддерж-ки JavaScript; Maps API для Flash; и даже Earth API, который позволяет загрузить на страницу приложение Google Earth для про-смотра трехмерного изображения земного шара, проведения виртуальных экскурсий и рисования фигур. Впрочем, для его ис-пользования необходимо установить модуль расширения Google Earth.
В: Существуют ли API для других язы-ков, кроме JavaScript?
О: Да! Доступно бесчисленное множество разных APIs, одни бесплатны, другие требу-ют приобретения лицензии. Если вы ищете некую функциональность, которую вам не хочется писать самостоятельно, вполне возможно, что для нее уже существует го-товый API.
Вы уже знаете, как заставить элементы реагировать на щелчки в jQuery. Как это поможет нам с выполнением последнего требования в списке?
Мозговой
штурм
частоЗадаваемые
вопросы
466 глава 11
и снова щелчки
var contentString = "This is an InfoWindow";
var my_infowindow = new google.maps.InfoWindow({
content: contentString
});
google.maps.event.addListener(my_marker, 'click', function() {
my_infowindow.open(map,my_marker);
});
Создаем экземпляр объекта Google Maps InfoWindow.
Определяем переменную с содержимым, которое нужно отобразить.
Приказываем карте прослу-шивать событие click для нашего объекта маркера.
Этот код выполняется
при щелчке на маркере
(на карте появляется
временное окно).
Задаем значение свойства content объекта InfoWindow.
Ïðîñëóøèâàíèå ñîáûòèé êàðòû
Мы уже почти подошли к концу. Вы уже видели разнообразные события, которые jQuery и JavaScript предоставляют для создания интересных интерактивных веб-приложений. Так как Google Maps API состоит из кода JavaScript (хотя и очень хорошо написанного и эффективного), он может использовать способность браузера прослушивать события и действовать соответствующим образом.
И по тем же причинам, по которым в jQuery были добавлены собственные функции создания слушате-лей, разработчики Google Maps предоставили возможность добавления слушателей событий через API. Не все браузеры одинаково работают со слушателями событий, и такой подход гарантирует, что API сможет управлять тем, как слушатели добавляются к странице. Ниже показано, как добавить слушателя события click для создания временного окна Google Maps InfoWindow.
В Google Maps API почти со всеми типами объектов (Map,
Marker, Line, InfoWindow, TrafficOverlay, Polygon и другие)
связываются события. И хотя события разных объектов часто
имеют одинаковые имена, они могут получать разные пара-
метры! Обязательно просмотрите документацию по объекту,
который вы намереваетесь использовать.
Для любознательных
дальше � 467
jquery и api
var info_window = new google.maps________________({content: ''});
function________________(type){
$.getJSON("________________ action=getSightingsByType&type="+type, function(json) {
if (json.sightings.length > 0) {
$('#sight_list').empty();
$.each(json.sightings,function() {
var info = 'Distance: ' + this[_________] + '<br>' + ' Height: ' + this['height'];
info += ', Weight: ' + this['weight'] + ', Color: ' + this['color'] + '<br>';
info += 'Latitude: ' + this['lat'] + ', Longitude: ' + this[_________];
var loc = new _____________________(this['lat'], this['long']);
var opts = {
map: map,
position:_____________
};
var marker = new google.maps _____________(opts);
markersArray.push(marker);
google.maps.event_____________(marker, 'click', function() {
info_window.content = info;
info_window.open(map, marker);
});
var $li = $("<li />");
$li.html('Date: ' + this['date'] + ', Type: ' + this['type']);
$li.addClass("sightings");
$li_________(function(){
info_window.content = info;
info_window.open(map, _________);
});
$li.appendTo("#sight_list");
_________ extend(loc);
});
map _____________ (bounds);
}
});
} maps.js
Возьми в руку карандашЗаполните пропуски в коде функции getSightingsByType, добавляющей функциональ-
ность обработки щелчков к маркерам на карте и к пунктам списка. Создайте глобальную пере-
менную info_window, которая представляет собой новый экземпляр объекта Google Maps
InfoWindow; по умолчанию объект инициализируется пустой строкой.
468 глава 11
решение упражнения
Обновленная функция getSightingsByType отображает данные в фор-
мате списка и на карте, а также заставляет маркеры карты и пункта списка
реагировать на щелчки.
var info_window = new google.maps ({content: ''});
function (type){
$.getJSON(" action=getSightingsByType&type="+type, function(json) {
if (json.sightings.length > 0) {
$('#sight_list').empty();
$.each(json.sightings,function() {
var info = 'Distance: ' + this[ ] + '<br>' + ' Height: ' + this['height'];
info += ', Weight: ' + this['weight'] + ', Color: ' + this['color'] + '<br>';
info += 'Latitude: ' + this['lat'] + ', Longitude: ' + this[ ];
var loc = new (this['lat'], this['long']);
var opts = {
map: map,
position:
};
var marker = new google.maps (opts);
markersArray.push(marker);
google.maps.event (marker, 'click', function() {
info_window.content = info;
info_window.open(map, marker);
});
var $li = $("<li />");
$li.html('Date: ' + this['date'] + ', Type: ' + this['type']);
$li.addClass("sightings");
$li (function(){
info_window.content = info;
info_window.open(map, );
});
$li.appendTo("#sight_list");
extend(loc);
});
map (bounds);
}
});
} maps.js
..fitBounds .
bounds.
marker
..click
..addListener
..Marker
loc
google.maps.LatLng"long''
‘distance'
service..php?
..InfoWindowgetSightingsByType
Добавляем слушателя события click к объекту Marker на карте.
Добавляем слушателя события к списку, чтобы на карте открывалось окно InfoWindow.
Возьми в руку карандаш Решение
дальше � 469
jquery и api
Включите в файл maps.js новый код, созданный нами на предыдущей странице. Затем откройте файл display_type.html в браузере и выберите существо в списке. Щелкните на маркерах списка, чтобы просмотреть дополнительную информацию о существе.
1. Создать раскрывающийся список типов существ (информация читается из базы данных).
2. При изменении состояния раскрывающегося списка получить из базы список существ выбран-ного типа.
3. Вывести информацию обо всех существах, полученную из базы данных, в списке и на карте.
4. И список, и маркеры на карте должны реагировать на щелчки, чтобы на карте отобража-лась дополнительная информация.
Тест-драйв
470 глава 11
вы — звезда jquery
Ïîëó÷èëîñü!!!
Всего на нескольких страницах вам удалось создать полностью работоспособный сайт, использующий код на нескольких языках (PHP, SQL, JavaScript и jQuery), а так-же работающий с Google Maps API средствами Ajax и JSON для отображения доволь-но сложных данных. Не так уж мало!
Меня когда-нибудь оставят в покое?
Сайт выглядит роскошно. Именно то, что мы хотели!
Спасибо!
дальше � 471
jquery и api
Âàø èíñòðóìåíòàðèé jQuery API
Глава 11 осталась позади, а вы научились использовать jQuery с разными API (а также JavaScript, PHP, MySQL, Ajax, JSON и не только!).
API Прикладные программные интерфейсы —
код, предоставляемый другими людьми
(или компаниями) для работы с их дан-
ными, объектами и различными видами
сервиса.
API предоставляют конструкторы, при
помощи которых вы создаете свои экзем-
пляры их объектов. Создавая экземпляр,
вы получаете возможность использования
всех методов и свойств, связанных с эти-
ми объектами, в своем коде.
ГЛА
ВА 10
472 глава 11
надеемся еще увидеться
Ïàðà ñëîâ íà ïðîùàíèå…
Жаль, что нам пора расставаться, но теперь вы знаете все необходимое для построения собственных сайтов, использующих jQuery, и вам пора заняться делом. Нам было приятно представить вам мир jQuery. Черкните нам пару строк или расскажите о своих классных разработках Feel на сайте Head First Labs:http://headfirstlabs.com.
Ðàäû áûëè âñòðåòèòüñÿ ñ âàìè â ñòðàíå jQuery!
Хочешь еще чем-нибудь поделиться со мной?
Приложение I. Остатки
Десять важных вещей(которые мы не рассмотрели)
Даже после всего сказанного многое осталось «за кадром». Существует масса других полезных возможностей jQuery и JavaScript, которые нам не удалось вместить в книгу. Было бы неправильно даже не упомянуть о них. Мы хотим, чтобы вы были готовы к любому аспекту jQuery, с которым вы можете столкнуться во время самостоятельных исследований.
474 приложение I
все без исключения
1. Âñå, ÷òî åñòü â áèáëèîòåêå jQuery
Вероятно, вы уже поняли, что библиотека jQuery огромна. Мы постарались представить основной материал, который может понадобиться новичку. Теперь вы знаете все необходи-мое и можете продолжить самостоятельное изучение библиотеки.
.add()
.addClass()
.after()jQuery.ajax().ajaxComplete().ajaxError()jQuery.ajaxPrefilter().ajaxSend()jQuery.ajaxSetup().ajaxStart().ajaxStop().ajaxSuccess().andSelf().animate().append().appendTo().attr().before().bind().blur()jQuery.browser.change().children().clearQueue().click().clone().closest()jQuery.contains().contents().context.css()jQuery.cssHooks.data()jQuery.data().dblclick()deferred.always()deferred.done()
deferred.fail()deferred.isRejected()deferred.isResolved()deferred.pipe()deferred.promise()deferred.reject()deferred.rejectWith()deferred.resolve()deferred.resolveWith()deferred.then().delay().delegate().dequeue()jQuery.dequeue().detach().die()jQuery.each().each().empty().end().eq().error()jQuery.errorevent.currentTargetevent.dataevent.isDefaultPrevented()event.isImmediatePropagationStopped()event.isPropagationStopped()event.namespaceevent.pageXevent.pageYevent.preventDefault()event.relatedTargetevent.resultevent.stopImmediatePropagation()event.stopPropagation()
event.targetevent.timeStampevent.typeevent.whichjQuery.extend().fadeIn().fadeOut().fadeTo().fadeToggle().filter().find().first().focus().focusin().focusout()jQuery.fx.intervaljQuery.fx.offjQuery.get().get()jQuery.getJSON()jQuery.getScript()jQuery.globalEval()jQuery.grep().has().hasClass()jQuery.hasData().height().hide()jQuery.holdReady().hover().html()jQuery.inArray().index().innerHeight().innerWidth().insertAfter().insertBefore()
Ìåòîäû jQuery
дальше � 475
остатки
1. Âñå, ÷òî åñòü â áèáëèîòåêå jQuery (ïðîäîëæåíèå)
.is()jQuery.isArray()jQuery.isEmptyObject()jQuery.isFunction()jQuery.isPlainObject()jQuery.isWindow()jQuery.isXMLDoc()jQuery().jquery.keydown().keypress().keyup().last().length.live().load().load()jQuery.makeArray().map()jQuery.map()jQuery.merge().mousedown().mouseenter().mouseleave().mousemove().mouseout().mouseover().mouseup().next().nextAll().nextUntil()jQuery.noConflict()jQuery.noop().not()jQuery.now().offset().offsetParent().one().outerHeight().outerWidth()
jQuery.param().parent().parents().parentsUntil()jQuery.parseJSONjQuery.parseXML().position()jQuery.post().prepend().prependTo().prev().prevAll().prevUntil().promise().prop()jQuery.proxy().pushStack().queue()jQuery.queue().ready().remove().removeAttr().removeClass().removeData()jQuery.removeData().removeProp().replaceAll().replaceWith().resize().scroll().scrollLeft().scrollTop().select().serialize().serializeArray().show().siblings().size().slice().slideDown()
.slideToggle()
.slideUp()
.stop()jQuery.sub().submit()jQuery.support.text().toArray().toggle().toggle().toggleClass().trigger().triggerHandler()jQuery.trim()jQuery.type().unbind().undelegate()jQuery.unique().unload().unwrap().val()jQuery.when().width().wrap().wrapAll().wrapInner()
Ìåòîäû jQuery (ïðîäîëæåíèå)
476 приложение I
все без исключения (продолжение)
1. Âñå, ÷òî åñòü â áèáëèîòåêå jQuery
Селектор "Все" ("*")Селектор "Атрибут содержит префикс" [name|="value"]Селектор "Атрибут содержит" [name*="value"]Селектор "Атрибут содержит слово" [name~="value"]Селектор "Атрибут завершается" [name$="value"]Селектор "Атрибут равен" [name="value"]Селектор "Атрибут не равен" [name!="value"]Селектор "Атрибут начинается" [name^="value"]:animated:button:checkbox:checkedСелектор дочерних элементов ("parent > child")Селектор классов (".class"):contains()Селектор потомков ("ancestor descendant"):disabledСелектор элементов ("element"):empty:enabled:eq():even:file:first-child:first:focus:gt()
Селектор "Имеет атрибут" [name]:has():header:hiddenСелектор идентификаторов ("#id"):image:input:last-child:last:lt()Селектор множественных атрибутов [name="value"][name2="value2"]Множественный селектор ("selector1, selector2, selectorN")Селектор "Следующий смежный" ("prev + next")Селектор следующих одноуровневых элементов ("prev ~ siblings"):not():nth-child():odd:only-child:parent:password:radio:reset:selected:submit:text:visible Selector
Ñåëåêòîðû jQuery
дальше � 477
остатки
2. jQuery CDN
CDN (Content Distribution Networks, «сети доставки контента») — большие сети серверов, предназначенные для хранения и распространения информации (данных, программ-ных продуктов, кода API, мультимедийных файлов и видеороликов и т. д.), обеспечи-вающие доступность информации в Интернете. Каждый узловой сервер содержит копию предоставляемых данных. Рациональное размещение узлов в Сети позволяет ускорить доступ к информации для многих пользователей. Примеры традиционных CDN — Windows Azure и Amazon CloudFront.
Многие крупные фирмы предоставляют копии jQuery в общедоступных сетях CDN. Ниже приводятся ссылки на копии jQuery, которыми вы можете пользоваться.
Вместо того чтобы каждый раз загружать код jQuery, вы можете включать в свои при-ложения эти ссылки.
http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.2.min.js
http://code.jquery.com/jquery-1.6.2.min.js (компактная версия)
Google Ajax API CDN
Microsoft CDN
jQuery CDN (через Media Temple)
http://code.jquery.com/jquery-1.6.2.js (исходная версия)
478 приложение I
метод noConflict
3. Ïðîñòðàíñòâî èìåí jQuery: ìåòîä noConflict
Многие библиотеки JavaScript используют символ $ в качестве имени функции или пере-менной, как это делает jQuery. В случае jQuery $ представляет собой синоним для имени jQuery, поэтому вся функциональность работает и без использования $. Если вам понадо-бится включить другую библиотеку JavaScript, кроме jQuery, передайте контроль за име-нем $ другой библиотеке, используя вызов $.noConflict:
<script type="text/javascript" src="other_lib.js"></script><script type="text/javascript" src="jquery.js"></script><script type="text/javascript">
$.noConflict(); //Код, использующий $ из других библиотек
</script>
Данный прием особенно эффективен в сочетании с возможностью метода . ready опре-делять синоним для объекта jQuery, так как в функции обратного вызова, передаваемой .ready, можно использовать $ без риска возникновения конфликтов:
<script type="text/javascript" src="other_lib.js"></script><script type="text/javascript" src="jquery.js"></script><script type="text/javascript"> $.noConflict();
jQuery(document).ready(function($) { // Код, использующий $ из jQuery }); // Код, использующий $ из других библиотек
</script>
Используйте этот прием только, если вы собираетесь работать с другими библиотеками JavaScript, использующими ссылку $. Если в вашей странице используется только библиоте-ка jQuery, все это вам не понадобится, даже в том случае, если страница включает несколько модулей расширения.
дальше � 479
остатки
4. Îòëàäêà êîäà jQuery
Отладка кода всегда полезна, особенно если вы работаете над крупномасштабным проектом, в котором используется множество разнообразных объектов, включаемых файлов или API. Нередко бывает нужно узнать содержимое полученного объекта или переменной, но вы не хотите выводить его в окне сообщения или вообще разбираться с получением свойств объекта.
На помощь приходят отладочные модули расширения. Они помогут заглянуть внутрь объектов, чтобы вы могли проследить за интересующими вас свойствами или пона-блюдать за изменением состояния переменной с течением времени, например узнать о непреднамеренном присваивании null. Все эти возможности чрезвычайно полезны при отладке кода JavaScript и jQuery.
При программировании на JavaScript и jQuery нам показались особенно полезными два отладочных модуля расширения — Dump и VariableDebugger.
http://plugins.jquery.com/project/Dump (для просмотра содержимого объектов).http://plugins.jquery.com/project/VariableDebugger (аналогично, но с выводом инфор-мации во временном окне).
Существуют и другие отладочные модули расширения, а со временем наверняка их будет все больше — как и усовершенствований уже существующих модулей. Эти моду-ли показались нам полезными, но если вам захочется поискать что-нибудь получше, посетите сайт jQuery Plug-ins (http://plugins.jquery.com/) и проведите поиск по слову «debug».
Конечно, в процессе отладки можно использовать вспомогательные средства браузе-ра, неоднократно упоминавшиеся в книге.
480 приложение I
очереди
5. Ðàñøèðåííàÿ àíèìàöèÿ è î÷åðåäè
Очереди в jQuery чаще всего используются для анимации, но вы можете использовать их так, как счи-таете нужным.
Очередь представляет собой массив функций, существующий на уровне элемента и хранящийся в jQuery.data. Очереди работают по принципу FIFO (First In, First Out, т. е. «первым вошел, первым вышел». Функции включаются в очередь вызовом .queue, а исключаются вызовом . dequeue.
Каждый элемент может иметь одну или несколько очередей функций, присоединенных к нему из jQuery. В большинстве приложений используется только одна очередь (fx). Очереди позволяют выполнить с элементом последовательность операций асинхронно, т. е. без прерывания программы. Типичный пример — последовательный вызов нескольких методов анимации для элемента:
$('#my_element').slideUp().fadeIn();
При выполнении этой команды анимация скольжения начинается немедленно, а проявление ставится в очередь fx и вызывается только при завершении перехода скольжения.
Метод .queue напрямую работает с содержимым очереди функций. Особенно удобен вызов .queue с передачей функции обратного вызова; он позволяет поместить новую функцию в конец очереди.
Данная возможность сходна с передачей функции методу анимации, но она не требует передачи функ-ции на момент запуска анимации.
$('#my_element').slideUp();$('#my_element').queue(function() { alert('Animation complete.'); $(this).dequeue();});
Эта запись эквивалентна следующей:
$('#my_element').slideUp(function() { alert('Animation complete.');});
Учтите, что при добавлении функции вызовом .queue для выполнения следующей функции в очереди необходимо вызвать функцию .dequeue.
В jQuery 1.4 вызываемая функция передается в первом аргументе другой функции. При ее вызове следу-ющий элемент автоматически выводится из очереди, а очередь продолжает двигаться:
$("#test").queue(function(next) { // Здесь что-то происходит... next();});
По умолчанию в jQuery используется очередь fx.
ПРИМЕЧАНИЕ. Если вы используете пользовательскую очередь, то должны вручную исключать функ-ции из очереди вызовом .dequeue. В отличие от очереди по умолчанию fx, пользовательские очереди не поддерживают автозапуск!
дальше � 481
остатки
6. Ïðîâåðêà ôîðì
К сожалению, нам не хватило места для описания такой важной возможности, как использо-вание jQuery для проверки данных форм на стороне клиента/браузера. В главах 9, 10 и 11 был приведен небольшой пример проверки данных на стороне сервера средствами PHP перед вставкой в базу. Проверка на стороне сервера очень важна, и даже можно сказать, необходима. Некорректно построенная команда insert или select может выдать намного больше инфор-мации о ваших данных, чем вы предполагали изначально.
Но вернемся к проверке данных на стороне клиента.
Существует много модулей расширения jQuery, предназначенных для этой цели. Одно из наших любимых решений — модуль «validation», доступный по адресу http://docs.jquery.com/Plugins/validation.
Этот модуль расширения позволяет определить набор правил для каждого элемента формы. В этих правилах вы настраиваете процедуру проверки и уточняете критерии правильности данных. Они могут быть любыми: минимальная или максимальная длина поля, проверка обя-зательных полей, проверка действительного формата адреса электронной почты и т. д. Далее приводятся некоторые примеры с сайта jQuery.
Элемент name определяется как обязательный, а элемент email — как обязательный и содержа-щий действительный адрес электронной почты.
$(".selector").validate({ rules: { // Простое правило, преобразуемое в {required:true} name: "required", // Составное правило email: { required: true, email: true } }});
Элемент определяется как обязательный (required) с минимальной длиной (minlength) 2, причем для обоих правил определяются пользовательские сообщения.
$("#myinput").rules("add", { required: true, minlength: 2, messages: { required: "Required input", minlength: jQuery.format("Please, at least {0} characters are necessary") }});
482 приложение I
эффекты jquery ui
7. Ýôôåêòû jQuery UI
Библиотека jQuery UI Effects содержит ряд дополнительных анимаций, отсутствующих в ба-зовой библиотеке jQuery. Эти эффекты можно разбить на три категории.
Цветовые анимацииЦветовые анимации расширяют функцию animate так, чтобы она могла анимиро-вать изменения цветов. Поддерживается цветовая анимация следующих свойств:
backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color outlineColor
1
Переходы классовПереходы классов расширяют базовый API классов так, чтобы он мог анимировать переход между двумя классами. jQuery UI изменяет следующие методы для передачи трех дополнительных параметров: speed, easing (необязательно) и callback.
addClass(class) Добавляет класс с анимированным переходом между состояниями.removeClass(class) Исключает класс с анимированным переходом между состояниями.toggleClass(class) Добавляет класс, если он отсутствует, или исключает его, если он входит в группу.switchClass(currentClass, newClass) Заменяет один класс другим с анимацией перехода.
2
Расширенное сглаживаниеРасширенное сглаживание (easing) включено в базовую функциональность Effects. Это jQuery-версия функций сглаживания, созданных Робертом Пеннерсом на ActionScript для Flash. Это математические формулы, позволяющие сделать анима-цию объектов более плавной и точной. Полный список всех функций сглаживания:
3
linear
swing
jswing
easeInQuad
easeOutQuad
easeInOutQuad
easeInCubic
easeOutCubic
easeInOutCubic
easeInQuart
easeOutQuart
easeInOutQuart
easeInQuint
easeOutQuint
easeInOutQuint
easeInSine
easeOutSine
easeInOutSine
easeInExpo
easeOutExpo
easeInOutExpo
easeInCirc
easeOutCirc
easeInOutCirc
easeInElastic
easeOutElastic
easeInOutElastic
easeInBack
easeOutBack
easeInOutBack
easeInBounce
easeOutBounce
easeInOutBounce
дальше � 483
остатки
8. Ñîçäàíèå ñîáñòâåííûõ ìîäóëåé ðàñøèðåíèÿ jQuery
Написание модулей расширения jQuery — исключительно полезная возможность, кото-рая экономит массу времени и усилий в ходе разработки. Самые сложные и ответственные функции абстрагируются в модули, предназначенные для повторного использования.
Вместо того чтобы долго объяснять тонкости создания модулей расширения jQuery, мы луч-ше предоставим это дело экспертам. Чрезвычайно содержательный и подробный учебник доступен по адресу http://docs.jquery.com/Plugins/Authoring.
Несколько рекомендаций для тех, кто только начинает заниматься разработкой собствен-ных модулей расширения jQuery.
Всегда заключайте свой модуль расширения в конструкцию (function( $ ){ // код модуля })( jQuery );.
Избегайте лишнего использования ключевого слова this в непосредственной об-ласти видимости функции вашего модуля расширения.
Если только ваш модуль расширения не возвращает конкретное значение, всег-да возвращайте из функции модуля расширения ключевое слово this (чтобы обеспечить возможность сцепления вызовов).
Вместо длинного списка аргументов передавайте конфигурацию вашего модуля расширения в виде объекта, поля которого могут заменять настройки по умол-чанию.
Не загромождайте объект jQuery.fn более чем одним пространством имен на каждый модуль расширения.
Всегда указывайте пространство имен для своих методов, событий и данных.
484 приложение I
замыкания
9. Çàìûêàíèÿ
Замыкания (closures ) — чрезвычайно сложный аспект JavaScript. Хотя замыкания не вошли в книгу, мы твердо убеждены в том, что они заслуживают хотя бы кратко-го упоминания.
Разобраться в замыканиях не так уж сложно. Необходимо понять основной прин-цип их работы. Но если ваше знакомство с темой начнется с чтения подробных технических описаний, это лишь собьет вас с толку.
Для начала пару определений…
Странно, не правда ли?
Замыкания полностью зависят от области видимости переменных и объектов, той области, в которой объекты, переменные и функции создаются и остаются доступны-ми и которая определяет контекст обращения к ним. Переменные, объекты и функ-ции могут определяться либо в локальной, либо в глобальной области видимости.
Локальная область видимости: определение чего-либо в ограниченной части кода (например, внутри функции).
Глобальная область видимости: глобальные переменные, объекты и функции, в отличие от локальных, доступны в любой точке вашего кода.
Рассмотрим следующий пример:
function func1(x) { var tmp = 3; function func2(y) { alert(x + y + (++tmp)); } func2(10);}func1(2);
Замыканием называется локальная переменная функции, которая продолжает существовать после возвращения управления.
Каждый раз, когда ключевое слово function встречается внутри другой функции, внутренняя функция имеет доступ к переменным внешней функции.
дальше � 485
остатки
10. Øàáëîíû
Шаблоны jQuery все еще находятся в фазе бета-тестирования, но уже сейчас можно ска-зать, что это полезный механизм, который поможет создавать более гибкие сайты без значительного объема кода HTML или jQuery. Шаблоны получают данные и связывают их с готовой разметкой, чтобы одна и та же разметка могла использоваться для отображения взаимосвязанных и похожих данных.
За дополнительной информацией обращайтесь по адресу: http://api.jquery.com/category/plugins/templates/.
9. Çàìûêàíèÿ (ïðîäîëæåíèå)Переменная tmp объявлена с локальной областью видимости внутри функции func1. В сообщениях будет выводиться значение 16, потому что func2 может обратиться к пере-менной x (определенной как аргумент func1), а также к значению tmp из func1.
Но это не замыкание. Замыкание возникает при возвращении внутренней функции, и эта внутренняя функция «замыкается» над переменными func1 перед выходом.
А теперь рассмотрим другой пример:
function func1(x) { var tmp = 3; return function (y) { alert(x + y + (++tmp)); }}var func2 = func1(2); // func2 is now a closure.func2(10);
И снова tmp определяется в локальной области видимости, но функция func2 имеет гло-бальную область видимости. Приведенная выше функция снова выдаст 16, потому что для func2 значения x и tmp продолжают оставаться доступными, хотя они и не находятся не-посредственно в ее области видимости.
Но поскольку переменная tmp находится в замыкании func2, она тоже будет увеличивать-ся при каждом вызове func2.
Существует техническая возможность создания нескольких функций замыкания, скажем, возвращением списка функций или посредством присваивания глобальным переменным. Все они будут обращаться к одним и тем же экземплярам x и tmp; они не будут создавать собственные копии.
Приложение II. Настройка среды разработки
Готовимся к великим свершениямВот начну учиться рано
и всех обгоню...
Вам понадобится среда, в которой вы сможете потренировать свои навыки PHP, но так, чтобы ваши данные не стали уязви-мыми для внешних атак. Разработку приложений PHP всегда жела-тельно начинать с безопасной среды и только потом открывать доступ для внешнего мира. В этом приложении приведены инструкции по установке веб-сервера, MySQL и PHP. После их выполнения в вашем распоряжении появится безопасная среда для работы и экспериментов.
488 приложение II
Прежде чем устанавливать компоненты среды разработки PHP, для начала проверьте, какие программы уже установлены на ком-пьютере. Рассмотрим три компонента и разберемся, как опреде-лить, какие из них уже установлены в системе.
Состав установленного программного обеспечения сильно зави-сит от платформы компьютера. В Mac OS X веб-сервер установлен по умолчанию, а на большинстве компьютеров Windows его нет.
Прежде чем вы сможете разместить готовое приложение в Web, необходимо разработать его с использованием ваших новых навыков jQuery и Ajax. Однако веб-приложение никогда не сле-дует разрабатывать в Web, где любой желающий сможет получить доступ к нему. Установите программное обеспечение локально, чтобы построить и полностью протестировать свое приложение до того, как переводить его в сетевой доступ.
Для построения и тестирования приложений PHP и MySQL необходимо установить на локаль-ном компьютере три программных продукта:
1. Веб-сервер
2. PHP
3. Сервер баз данных MySQL
PHP — не сервер, а набор правил, которые «понимает» веб-сервер (они нужны, чтобы интер-претировать код PHP). Веб-сервер и сервер MySQL — исполняемые программы, запускаемые на компьютере.
Помните, что речь идет о настройке локального компьютера для выполнения функций веб-сервера при разработке PHP. Вам также потребуется полноценный сетевой веб-сервер, чтобы размещать готовые приложения.
×òî ó âàñ óæå åñòü?
Ñîçäàíèå ñðåäû ðàçðàáîòêè PHP
Примечание: материал приложения относитсяк Windows XP, Vista, Windows 7 и Windows Server 2003/2008,а на платформе Mac — к Mac OS X 10.3.x и более новых версий.
Веб-сервер
Сервер баз данных
Серверный компьютер
Сервер баз данных MySQL часто устанавливает-ся на одном компьютере с веб-сервером. В данной ситуации это ваш локаль-ный компьютер!
Поддержка PHP устанавлива-ется как часть веб-сервера и позволяет веб-серверу вы-полнять сценарии PHP.
В среде разработки PHP локальный компьютер вы-полняет функции серверного компьютера в отношении выполнения сценариев PHP.
Для предоставления сценариев PHP в виде веб-страниц потре-буется программный продукт, называемый веб-сервером,например Apache или IIS.
локальная установка php и mysql
дальше � 489
настройка среды разработки
Ó âàñ óñòàíîâëåí âåá-ñåðâåð?
Ó âàñ óñòàíîâëåíà ïîääåðæêà PHP? Êàêàÿ âåðñèÿ?
Если вы работаете на новом PC или Mac, возможно, веб-сервер уже установлен. Откройте окно браузе-ра и введите в адресной строке команду адрес http://localhost. Если в браузере откроется заставка, это означает, что веб-сервер установлен и нормально работает.
Если веб-сервер установлен, вы сможете легко проверить, установлена ли у вас поддержка PHP, и какая именно версия. Создайте сценарий с именем info.php и включите в него следующую команду:
<?php phpinfo(); ?>
Сохраните файл в каталоге, используемом веб-сервером. В Windows типичная команда выглядит так:
C:\inetpub\wwwroot\ (для IIS)
или:
C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs (для Apache)
А вот как она обычно выглядит на Mac:
/Users/yourname/sites/
Если вы захотите открыть этот файл в своем браузере по адресу http://localhost/info.php,то при установленной поддержке PHP результат будет примерно таким:
На компьютере Windows с IIS заставка выглядит примерно так.
Если вы работаете на ком-пьютере Mac или Windows с установленным веб-сервером Apache, заставка выглядит примерно так.
Установленная версия PHP
Windi dows
вы р баботае
490 приложение II
$ cd /usr/local/mysql
$ mysqlWelcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 3Server version: 5.0.51b MySQL Community Server (GPL)Type 'help;' or '\h' for help. Type '\c' to clear the buffer.mysql>
File Edit Window Help IHeartPHP
Ó âàñ óñòàíîâëåí MySQL? Êàêàÿ âåðñèÿ?
Чтобы проверить наличие MySQL на Mac, откройте терминал и введите:
cd /user/local/mysql
Если команда работает, значит сервер MySQL установлен. Для проверки версии введите команду:
mysql
Если коман-да выполне-на успешно, значит сер-вер MySQL установлен.
Версия MySQL, установлен-ная в вашей системе
В системе Windows щелкните правой кнопкой мыши на панели задач Windows, выберите Диспетчер задач и перейдите на вкладку Службы.
Проверьте, есть ли MySQL в списке.
Терминал MySQL также называется «монитором» MySQL.
проверка версии mysql
дальше � 491
настройка среды разработки
Íà÷íåì ñ âåá-ñåðâåðà
В зависимости от того, какая версия Windows установлена на вашем компьютере, вы можете загру-зить Microsoft IIS (Internet Information Server) или Apache, веб-сервер с открытым кодом. Если вам нужен сервер для Mac, вероятно, стоит остановиться на веб-сервере Apache, потому что он уже уста-новлен на вашем компьютере.
Далее приводится краткое описание установки Apache в Windows.
Откройте страницу http://httpd.apache.org/download.cgi.
Если вы используете Windows, мы рекомендуем загру-зить файл apache_2.2.19-win32-x86-no_ssl.msi. Когда файл будет загружен, сделайте на нем двойной щелчок, чтобы начать автоматическую установку.
Загрузите эту версию и сделайте на ней двойной щелчок после загрузки.
Открывается окно мастера установки. Инструкции в основном понятны без пояснений, и в большинстве случаев вы можете подтвердить выбор по умолчанию.
Выберите домен, к кото-рому принадлежит ваш компьютер. Если домена нет, введите localhost.
Проще всего выбрать ти-пичный вариант установки.
Обычно для установки про-граммного продукта можно выбрать каталог по умолча-нию.
492 приложение II
Óñòàíîâêà Apache... çàâåðøåíèå
Работа почти закончена. Щелкните на кнопке Install и подождите пару минут. Вот и все!
Веб-сервер настраивается на автоматический запуск при загрузке системы. Впрочем, вы можете останавливать и запускать его по своему усмотрению в диалоговом окне Па-нель управления�Администрирование�Службы. Веб-сервер находится в списке под именем Apache2.2.
Óñòàíîâêà PHPЕсли вы используете Windows, откройте страницу http://www.php.net/downloads.php или http://windows.php.net/download.
Для Windows мы также рекомендуем загрузить соответствующую версию с автомати-ческой установкой. Пользователи Apache загружают файл php-5.2.17-Win32-VC6-x86.msi, а пользователи IIS — файл php-5.3.6-Win32-VC9-x86.msi. Загрузите файл и двойным щелч-ком начните автоматическую установку PHP.
Раздел загрузки версий для Windows в формате .msi Прочитайте описание
и выберите версию.
Загрузите файл и сделайте на нем двойной щелчок. Кнопка Run начинает установку.
установка php
Если эти инструкции вам не подошли, повторите попытку или введите строку «установ-ка Apache в Windows» в поисковой системе.
дальше � 493
настройка среды разработки
Äåéñòâèÿ ïî óñòàíîâêå PHP
Для начала необходимо принять несколько три-виальных решений.
Примите условия ли-цензионного соглаше-ния, чтобы продолжить установку.
Обычно PHP рекомендует-ся устанавливать в папку по умолчанию, но вы можете указать другую папку.
Будьте внимательны. Если вы используете Apache, выберите правильную версию. Если вы используете ISAPI, то, скорее всего, следует выбрать модуль IISAPI. За до-полнительной информацией обращайтесь к документации. В данном примере был выбран веб-сервер Apache 2.2, а на следующем экране вводится путь к установленно-му экземпляру Apache.
Прокрутите список Extensions и выберите MySQL. Это позволит использовать встроенные функции PHP по работе с MySQL, использованные в книге!
Прокрутите список в категории Extensions и щелкните на пункте MySQL. Выберите вариант «Entire feature».
494 приложение II
Также вам потребуется сервер баз данных MySQL; давайте разберемся, как загрузить и установить его. Бесплатная версия РСУБД MySQL сейчас официально называется MySQL Community Server.
Ниже приведено описание последовательности действий по установке MySQL в Windows и Mac OS X. Эта краткая сводка не заменит превосходных инструкций с сайта MySQL; мы настоятельно рекомендуем посетить сайт и прочитать их! За более подробным описанием и рекомендациями по решению проблем обращайтесь по адресу:
Также вам пригодится программа просмотра запросов MySQL, которая позволяет ввести запрос и ознакомиться с результатами в интерфейсе приложения (вместо консольного окна).
http://dev.mysql.com/doc/refman/5.5/en/windows-installation.html
Èíñòðóêöèè è ðåøåíèå ïðîáëåì
Загрузите версию 5.5 и выше.
Óñòàíîâêà MySQL
Вот и все! Щелкните на кнопках Install и Done, чтобы закрыть программу установки.
Äåéñòâèÿ ïî óñòàíîâêå PHP... çàâåðøåíèå
установка mysql в windows
Если инструкции вам
не подошли,
повторите попытку
или введите
«установка PHP
для Apache [или IIS]
в Windows»
в поисковой системе.
Создайте новый сценарий с именем info.php и включите в него команду:
<?php phpinfo(); ?>
Сохраните файл в каталоге своего веб-сервера. В системе Windows это обычно папка
C:\inetpub\wwwroot\ (для IIS) или
C:\Program Files (x86)\Apache Software Foundation\Apache2.2\htdocs (для Apache). На Mac обычно используется /Users/yourname/sites/.
Откройте файл в браузере: http://localhost/info.php,
Если поддержка PHP была установлена успешно, результат должен выглядеть примерно так:
дальше � 495
настройка среды разработки
Óñòàíîâêà MySQL â ñèñòåìå Windows
Немного прокру-тите вниз.
Откройте страницу:http://dev.mysql.com/downloads/
И щелкните на кнопке «Download the Beta» в разделе MySQL Installer for Windows. (Примечание: на момент написания книги существовала только бета-версия.)
1
Выберите в списке Microsoft Windows.2
496 приложение II
Щелкните на ссылке No thanks, just take me to the downloads! (если только вы не хотите зарегистрироваться на сайте или у вас уже имеется учетная запись).
Когда откроетсядиалоговое окно ма-стера установки, щелкните на кнопке Install MySQLProducts.
Çàãðóçêà ïðîãðàììû óñòàíîâêè
Продолжитьбез регистрации.
установка mysql в системе windows (продолжение)
Выберите версию 5.5.13 и выше.
Верхний вариант!
Выберите в списке Windows(x86, 32-bit), MSI Installer.3
На странице выводится список серверов, на которых доступна нужная версия продукта. Выберите ближайший к вам сервер.
4
Когда файл будет загружен, щелкните на нем правой кнопкой мыши и выбе-рите команду «Запуск от имени администратора» (если у вас включен меха-низм Windows UAC). Дальнейшая установка будет осуществляться под руко-водством мастера установки. Щелкните на кнопке Next.
5
дальше � 497
настройка среды разработки
Âûáîð ïàïêè äëÿ óñòàíîâêè
Прочитайте текст лицензии, согласитесь на ее условия и щелкните на кноп-ке Next.
6
На следующем шаге выполняется автоматическая проверка на наличие новых версий. Если вы хотите пропустить ее, установите флажок Skip Check. Лучше, чтобы приложение устанавливалось в самой последней версии. После обнов-ления нажмите Next, чтобы продолжить установку.
7
498 приложение II
установка mysql в системе windows (продолжение)
Вам будет предложено выбрать тип установки. Для наших целей идеально подойдет стандартный вариант для разработчиков ( Developer Default). Оставьте пути установ-ки, предложенные по умолчанию, и нажмите Next.
8
Программа установки проверяет совместимость с Microsoft .NET Framework 4 Client Profile. Это необходимо для приложения MySQL Workbench. Если проверка не про-ходит, обновите Windows на сайте http://update.microsoft.com/.
9
В следующем окне перечислены все устанавливаемые компоненты. Щелкните на кнопке Execute, чтобы начать установку.
10
дальше � 499
настройка среды разработки
После подтверждения успешной установки всех компонентов нажмите Next, чтобы перейти к настройке конфигурации службы MySQL. Установите переклю-чатель Developer Machine и нажмите Next.
11
Убедитесь в том, что флажки Enable TCP/IP Networking и Create Windows Service установлены. Оставьте в других полях значения по умолчанию. Введите пароль привилегированного пользователя MySQL, нажмите Next.
12
Установка завершается. Если приложение MySQL Workbench не запустилось ав-томатически, запустите его командой меню Пуск�Все программы�MySQL.
13
500 приложение II
Если вы используете Mac OS X Server, в вашей системе уже должна быть установлена вер-сия MySQL.
Прежде чем продолжать, проверьте, нет ли в вашей системе установленного экземпляра MySQL (выберите команду Applications/Server/MySQL Manager).
Óñòàíîâêà MySQL â Mac OS X
Прокрутите вниз.
установка mysql в системе mac os x
Поддержка PHP входит в Mac OS X версии 10.5+ (Leopard), но по умолчанию она заблоки-рована. Чтобы включить ее, необходимо открыть основной файл конфигурации Apache http.conf и убрать комментарий в одной строке кода. Этот файл находится в папке установ-ки Apache.
Найдите строку кода, которая начинается с «решетки» (#) — признака комментария:
Âêëþ÷åíèå ïîääåðæêè PHP â Mac OS X
#LoadModule php5_module libexec/apache2/libphp5.so
Удалите «решетку» и перезапустите сервер, чтобы активизировать поддержку PHP. Вла-дельцем файла http.conf является пользователь «root», а это означает, что для его измене-ния вам придется ввести свой пароль. Вероятно, вам также придется внести изменения в файл php.ini. За подробной информацией о том, как выполнить эти действия и включить поддержку PHP, обращайтесь по адресу http://foundationphp.com/tutorials/php_leopard.php.
Откройте страницу:http://dev.mysql.com/downloads/
и щелкните на ссылке MySQL Community Server.
В этом описании используется 32-разрядная версия. Убедитесь в том, что за-гружаемая версия соответствует вашей операционной системе.
1
дальше � 501
настройка среды разработки
Чтобы найти ее, список придется прокрутить!
Щелкните на кнопке Download для версии Mac OS X v10.6 (x86, 32-bit), DMG Archive.
2
Щелкните на ссылке No thanks, just take me to the downloads! (если только вы не хотите зарегистрироваться на сайте или у вас уже имеется учетная запись).
3
Для ускорения загрузки выберите сервер, расположенный ближе всего к вам.
Продолжить без регистрации.
502 приложение II
Щелкните на ссылке No thanks, just take me to the downloads! (если только вы не хотите зарегистрироваться на сайте или у вас уже имеется учетная за-пись) и снова выберите зеркальный сервер для загрузки.
Çàãðóçêà óñòàíîâî÷íîãî ïàêåòà
Продолжить без регистрации.
установка mysql в системе mac os x (продолжение)
Вернитесь на страницу:http://dev.mysql.com/downloads/
и щелкните на ссылке MySQL Workbench.
44
Когда загрузка обоих файлов будет завершена, сделайте двойной щелчок на файле mysql-5.5.14-osx10.6-x86.dmg, а затем на файле mysql-5.5.14-osx10.6-x86.pkg, чтобы запустить программу установки пакета.
5
Установочный пакет
дальше � 503
настройка среды разработки
Çàïóñê óñòàíîâêè ïàêåòà
Начинается установка. Нажмите Next, чтобы перейти к странице Read Me, а за-тем нажмите Continue, чтобы перейти к странице с лицензионным соглашением.
6
В следующем окне выводится текст лицензионного соглашения MySQL. Если вы согласны на его условия, щелкните на кнопке Continue, а затем на кнопке Agree. Снова щелкните на кнопке Continue, чтобы установить MySQL в каталог по умол-чанию.
7
504 приложение II
Через некоторое время появляется сообщение об успешном завершении установки.
установка mysql в системе mac os x (продолжение)
Щелкните на кнопке Install, введите имя и пароль администратора и щелкните на кнопке OK, чтобы начать установку.
48
Повторите те же действия для файла MySQLStartupItem.pkg.9
Установочный пакет
дальше � 505
настройка среды разработки
Сделайте двойной щелчок на файле MySQL.prefPane, также входящем в образ mysql-5.5.14-osx10.6-x86.dmg, для установки приложения MySQL Preference Pane; за-тем щелкните на кнопке Start MySQL Server.
10
Установочный пакет
506 приложение II
установка mysql в системе mac os x (продолжение)
Сделайте двойной щелчок на файле mysql-workbench-gpl-5.2.34.osx-i686.dmg (который также был загружен ранее), чтобы запустить процесс установ-ки программы MySQL Workbench.
11
Перетащите значок MySQLWorkbench.app в папку Applications.
Запустите программу Workbench из списка приложений.
дальше � 507
настройка среды разработки
Убедитесь в том, что сервер работает (панель Server Administration). Если панель пуста, щелкните на ссылке New Server Instance и выберите сервер.
12
Создайте новое подключение в разделе SQL Development: щелкните на ссылке New Connection и введите данные в открывшемся окне. Затем сделайте двойной щелчок на новом подключении, чтобы открыть его.
13
За дополнительной информацией о MySQL и MySQL Workbench обращайтесь по адресу http://dev.mysql.com/doc/.
Райан Бенедетти, Ронан Крэнли
Изучаем работу с jQuery
Перевел с английского Е. Матвеев
Заведующий редакцией А. Кривцов Руководитель проекта А. Юрченко Ведущий редактор Ю. Сергиенко Литературный редактор Б. Файзуллин Художественный редактор Л. Адуевская Корректор В. Ганчурина Верстка Е. Леля
ООО «Мир книг», 198206, Санкт-Петербург, Петергофское шоссе, 73, лит. А29. Налоговая льгота — общероссийский классификатор продукции ОК 005-93, том 2;
95 3005 — литература учебная. Подписано в печать 16.05.12. Формат 84х108/16. Усл. п. л. 55,440. Тираж 2000. Заказ
Отпечатано в ОАО «Первая Образцовая типография», филиал «Дом печати - ВЯТКА» в полном соответствии с качеством предоставленного оригинал-макета.
610033, г. Киров, ул. Московская, 122 Факс: (8332) 53-53-80, 62-10-36