Text
                    Исчерпывающее руководство об основном языке сценариев
для создания полнофункциональных\Л/еЬ-приложений
Исследуется связь JavaScript с другими Web-технологиями
как со стороны клиента, так и со стороны сервера
Э* Своевременные решения
Объектно-ориентированная
методология и ее воплощение в
JavaScript
Фундаментальные основы языка
JavaScript
Операторы, управляющие
структуры, функции и базовые
объекты
¦	Исчерпывающий анализ объектной
модели документов
Объекты, используемые со
стороны клиента и со стороны
сервера
¦	Помещение на Web-страницы
эффектов, характерных для
динамического HTML
Устойчивая работа сценариев в
браузерах Netscape Navigator и
Microsoft Internet Explorer
Сопровождающий CD-ROM
Исходные тексты всех примеров,
рассмотренных в книге
Полезные инструментальные
средства независимых
разработчиков
Многое другое
SAMS
PUBLISHING
.-. книга-почтой [ интернет-магазин
www.diasoft.kiev.ua


JavaScript тм THIRD EDITION R. Allen Wyke, etal. SAMS A Division of Macmillan USA 201 West 103rd Street Indianapolis, Indiana 46290 UNLEASHED
ЭНЦИКЛОПЕДИЯ ¦ ¦¦— ^- Toorono-издательский гагам I ^.дат. ^ _-». ^^ ifjff .Jit ^ ,в$? ^ jf/"W ^iP JFjtM ^^ Ш 1 торгово-издательский жим DiaSoft Аллеи Вайк и др. Основана в 1996 г. тм Киев • ООО "ТИД" ДС" . 2001
УДК004.43@31) ББК 32.973.26-018.1 В 14 ВАЙК Аллен и др. В14 JavaScript. Энциклопедия пользователя: Пер.с англ./Аллен Взйк.— К.: ООО "ТИД"ДС", 2001,—480с, ISBN 966-7992-00-04 Книга JavaScript. Энциклопедия пользователя является наиболее полным учебным и справочным руковод- руководством по всем версиям языка JavaScript, включая JavaScript 1.5и JScript 5.0. На сегодняшний день JavaScript представляет собой самый распространенный язык для написания сценариев, обеспечивающих поддержку интерактивного содержимого Web-страниц. Книга охватывает широкий спектр вопросов, начиная с основ языка и заканчивая сложными вопросами практического применения технологий Web-дизайна. Подробно рассматриваются: взаимодействие JavaScript и HTML; типы данных, операции, выражения и операторы; основы объектно-ориентированной методологии и ее реализация в JavaScript; объекты со стороны клиента и сервера; DHTML; технологии написания устойчивого и надежного кода; методика отладки кода. Особое вни- внимание в книге уделяется вопросам достижения безопасности Web-приложений. Книга изобилует множеством практических примеров, которые покрывают всю специфику разработки Web-сайтов с использованием JavaScript.Справочник по базовым языковым объектам превращает книгу в истинное настольное руководство. Сопровождающий CD-ROM содержит исходные коды всех примеров, рассмотренных в книге, а также множество другой полезной информации. JavaScript. Энциклопедия пользователя рассчитана на широкий круг разработчиков Web-приложений. Учебное издание ББК 32.973.26-018.1 ВАЙК Аллен и др. JAVASCRIPT. ЭНЦИКЛОПЕДИЯ ПОЛЬЗОВАТЕЛЯ Головний редактор Ю.Н.Артеменко Верстка Г.А.Булавко Головний дизайнер О.А.Шадрт Здано на складання 20.07.2001. Пщписанодо друку 20.09.2001. Формат 84x108/16. ITanip ¦офсетний. Гарнпура Тайме. Друк офсетний. Умовн.друк.арк. 34,80. Обл.-вид.арк. 34,80 Тираж 2000 прим. Замовлення № 1-158. ТОВ "ТВД"ДС", 04053, Киш-53, вул. Артема 25, а/я 100, тел./факс @44) 212-1254. e-mail: books@diasoft.kiev.ua, http://www.diasoft.kiev.ua. Свщоцтво про внесения суб'екта видавничо! справи до Державного реестру видавщв, виготшниюв i роз- повсюджувач!в видавничо! продукци: сер!я — ДК, №558 вщ 09.08.2001р. Отпечатано в соответствии с качеством предоставленных диапозитивов на ОАО «Белоцерковская книжная фабрика» 09117, г. Белая Церковь, ул. Леся Курбаса, 4 Authorized translation from the English language edition published by Sams Copyright ©2001 All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Russian language edition published by DiaSoft Publishing. Copyright © 2001 Лицензия предоставлена издательством Sams Corporation, подразделение Macmillan Computer Publishing. Все права зарезервированы, включая право на полное или частичное воспроизведение в какой бы то ни было форме. ISBN 966-7992-00-4 © Перевод на русский язык. ООО "ТИД" ДС", 2001 ISBN 0-672-31763-Х (англ.) © Sams Corporation, 2001 © Оформление. ООО "ТИД" ДС", 2001 Гигиеническое заключение № 77.99.6.953.П.439.2.99 от 04.02.1999
Оглавление Введение13 Часть I. Знакомство с JavaScript 15 Глава 1. JavaScript и World Wide Web 16 Знакомство с JavaScript 16 Десять заповедей JavaScript, которые должен знать каждый создатель сценариев 17 JavaScript можно внедрить в HTML 17 JavaScript зависит от среды 18 JavaScript — интерпретируемый язык 19 JavaScript — слабо типизированный язык 19 Javascript — объектно-ориентированный язык .... 19 JavaScript — язык, управляемый событиями 20 JavaScript — это не Java 20 JavaScript —многофункциональный язык 20 JavaScript — развивающийся язык 20 Сферы использования JavaScript 20 Четыре фазы развития World Wide Web 21 Фаза 1. Символьный гипертекст 21 Фаза 2. Графически-ориентированные статические HTML-документы 21 Фаза 3. Динамические HTML-документы 21 Фаза 4. Активные HTML-документы 22 Среда разработки Web-приложений 22 Клиентская часть 23 Серверная часть 25 Что можно сделать при помощи JavaScript? 27 Клиентские приложения 27 Проверка допустимости данных 27 Создание интерактивных форм 27 Клиентские таблицы поиска 27 Поддержка состояния 27 Работа с Java-аплетами, элементами управления ActiveX и подключаемыми модулями 27 Поддержка JavaScript со стороны браузеров 28 Netscape Navigator. 28 Microsoft Internet Explorer 28 Другие браузеры 28 Сравнение JavaScript и JScript 28 Что такое VBScript? 28 Программирование в VBSript 30 Резюме .. ..31 Глава 2. Совместная работа JavaScript и HTML 32 Основы HTML 32 Текущая ситуация 32 Основы HTML 33 Структура HTML-документа 33 Основное об атрибутах 34 Внедрение JavaScript в HTML 34 Атрибуты дескриптора <script> 34 Просмотр кода JavaScript 37 Создание JavaScript-кода 37 Выполнение сценариев 37 Учет браузеров, не поддерживающих JavaScript 39 Написание кода 40 Выполнение сценариев 41 Резюме 41 Глава 3. Создание собственного набора инструментальных средств JavaScript 42 Необходимые инструментальные средства 42 JavaScript-редакторы 42 HTML-редакторы 43 Web-браузеры 44 Отладчики сценариев 45 Процесс разработки на JavaScript 45 Серверные инструментальные средства JavaScript 45 Netscape's Server-Side JavaScript 45 Borland JntraBuilder 45 Резюме 45 Глава 4. Создание первого сценария 46 Краткое напоминание 46 Перед началом работы 46 Какие браузеры будут поддерживаться? 46 Как следует учитывать браузеры, не noflaepxHBaioLMHeJavaScript? 47 Встроить код или вынести его в отдельный файл? 48 Каковы ваши цели? 48 Приступаем к созданию сценария 48 Определение целей 49 Создание шаблона кода 49
JavaScript. Энциклопедия пользователя щ Учет He-JavaScript-браузеров 49 Написание кода 49 Вызов функции 50 Первый сценарий 50 Резюме 51 Часть II. Базовое подмножество языка JavaScript 52 Глава 5. Основы языка JavaScript 53 Краткое резюме 53 Как JavaScript связан с CGI, дополнительно вставляемыми модулями и Java 53 CGI 53 Подключаемые модули 54 Java 54 Внедрение сценариев в HTML-документы 55 События 56 Синтаксис 56 Версии JavaScript 56 Лексемы 57 Переменные 60 Константы 63 Цвета 63 Типы данных 64 Выражения 64 Комментарии 66 Функции 67 Резюме 68 Глава 6. Операции 69 Операции присваивания 70 Арифметические операции 70 Операции сравнения 71 Строковые операции 73 Условные операции 74 Булевы операции 74 Операция typeof 74 Определение и вызов функций 75 Операции со структурами данных 75 Поразрядные операции 75 Поразрядные логические операции 76 Поразрядные операции сдвига 76 Зачем вообще возиться с разрядами? 77 Приоритеты выполнения операций 79 Резюме 80 Глава 7. Управляющие структуры и организация циклов 82 Условные операторы 82 if .. .. 82 ,if..else 84 try..catch 85 Операторы организации циклов 85 for 85 for..in ! 87 while 88 do..while 88 break и continue 88 Метки 89 Операторы with 90' Оператор switch 91 Резюме 91 Глава 8. Функции 93 Понятие функций 93 Создание функций 93 Где объявлять функции 94 Вызов функции 94 Использование аргументов 94 Изменение количества аргументов 96 Использование глобальных и локальных переменных 99 Передача объектов по ссылке 100 Дополнительные сведения о функциях 101 Повторное использование функций 101 Рекурсивные функции 101 .Резюме 102 Глава 9. Объекты со стороны клиента 103 Понятие объекта 103 Объекты 103 Инкапсуляция 106 Сообщения 107 Классы 107 Объекты JavaScript 109 Точечная нотация 109 Исследование объектной модели JavaScript 110 Отношения содержания в JavaScript 110 Свойства 111 Методы 111 События 112 Дополнительная информация об объектах 113 Объект navigator 114 Объект Window. 116 Объекты верхнего уровня 119 Объекты второго уровня 122 Объекты третьего уровня 126 Объекты четвертого уровня 129 Резюме 130
Оглавление Глава 10. Основные объекты языка .... 131 Объект Global 131 Объект String 131 Примеры манипуляций со строками 134 Форматирование строк 135 Работа со специальными символами 139 Преобразование строк и чисел 140 Объект RegExp 141 Объект Array 141 Объект Date 144 Объект Math 147 Объект Boolean 148 Объект Number 149 Объект Function 149 Резюме 150 Глава 11. Создание пользовательских объектов JavaScript 151 Создание объектов 151 Создание экземпляров 153 Работа с экземплярами объектов 154 Создание составных объектов 156 Динамическое создание объектов 159 Расширение экземпляров объектов 162 Резюме 162 Глава 12. Серверная часть JavaScript 163 Использование архитектуры клиент/сервер 163 Web-приложения с клиент-серверной архитектурой 163 Передача информации между клиентом и сервером 164 Управление сеансами 165 Разработка серверных приложений JavaScript 166 Создание исходных файлов 166 Подготовка приложения 168 Исправление ошибок 170 Базовые серверные объекты JavaScript 172 Объект Server. 172 Объект Project 173 Объект Client 173 Объект Request 174 Объект Lock 175 Объект File 175 Объект SendMail 177 Объекты баз данных 178 Резюме .... ..181 Часть III. Использование DOM 182 Глава 13. Основы объектной модели документа (DOM) 183 'Понятие объектной модели документа 183 От DHTML к DOM 183 Навигация по таблице 184 Управление документами 184 Объектная модель и атрибуты 185 Навигация по документу. 186 Резюме 187 Глава 14. Управление событиями 188 Понятие событий и обработчиков событий 188 Обработчики событий JavaScript 188 Щелчок на объекте (onClick) 189 Отправка формы (onSubmit) 190 Сброс формы (onReset) 190 Изменение данных (onChange) 191 Получение фокуса (onFocus) 191 Выход из фокуса (onBlur) 192 Выделение текста (onSelect) 193 Перемещение мыши по объектам (onMouseOver и onMouseOut) 193 Загрузка документа (onLoad) 196 Выход из документа (onUnload) 197 Обработка ошибок (onError) 197 Прерывание загрузки изображения (onAbort) 198 Замена обработчиков событий 198 Программная генерация событий 198 События таймера 198 Резюме 199 Глава 15. Объект Window 200 Объект Window. 200 Открытие и закрытие окон 201 Ссылки на окна 202 Определение содержимого окна 202 Определение атрибутов окна 202 Закрытие окон 204 Навигация между окнами 207 Косвенная установка фокуса 207 Прямая установка фокуса 208 Удаление фокуса 208 Отображение окон сообщений 208 Простое уведомление 208 Yes/No-подтверждение 210 Пользовательский ввод 210 Работа с сообщениями строки состояния 212 Резюме .. ...213
JavaScript. Энциклопедия пользователя Глава 16. Объект Document 214 Объект Document 214 Программное создание HTML-документов 214 Изменение цвета документа 216 Объект Link 218 Ссылки на объекты Link 219 Выполнение JavaScript-кода для ссылок 220 Объект Anchor 223 Объект Image 223 Резюме 224 Глава 17. Объекты Form 225 Объект Form 225 Отправка формы на сервер 225 Проверка элементов в Form 227 Объект Text 229 Присваивание объекту Text значения по умолчанию 229 Выделение текста в фокусе 230 Захват данных с помощью объекта Textarea 231 Перенос текста в объекте Textarea 231 Объекты Button: Submit, Reset и Button 231 Объект Checkbox 233 Определение заполнения объекта Checkbox 233 Объект Radio 234 Определение значения выбранного переключателя 234 Объект Select : 235 Создание списка выбора 235 Создание прокручиваемого списка 236 Создание прокручиваемого списка с мультивыбором 236 Определение значения или текста выбранной опции 237 Определение значений в прокручиваемых списках с мультивыбором 237 Выбор опции с помощью JavaScript 238 Объект Password 238 Объект Hidden 239 Резюме 241 Глава 18. Объекты Frame 242 Объект Frame 242 Создание фреймов 243 Размещение дескрипторов 244 Добавление JavaScript-кода ко фреймам 246 Синхронизация фреймов 247 Обновления фреймов 249 Сценарии для фреймов с картами изображений 252 Работа с фреймовыми URL 254 Ссылки на фреймы 254 Ссылки из дочернего фрейма на родительский 256 Объект Location 260 Открытие нового URL 260 Работа со свойством protocol 261 Объект History. 262 Определение размеров списка 262 Навигация по списку посещений 262 Объект Navigator 264 Резюме 265 Глава 19. Другие DOM-объекты 266 DOM-браузеры 266 Управление DOM-документами и DOM-методы 268 Использование метода cloneNode 268 Использование метода insertBefore в DOM 269 Использование метода swapNode 269 Использование метода removeNode 269 Резюме 270 Часть IV. Технологии программирования на динамическом HTML 271 Глава 20. Динамическая подмена 272 Знание событий 272 onMouseOver 272 ¦onMouseOut 272 onMouseDown 272 on MouseUp 272 Виды динамических подмен 272 Rollover-эффекты для изображений 273 ЯоНоуег-эффекты для слоев 274 Резюме 276 Глава21. Визуальные эффекты 277 Бегущие строки 277 Баннеры 278 Постепенное изменение цветов 281 Анимированные командные кнопки 282 Резюме 284 Глава 22. Каскадные таблицы стилей 285 Основные концепции таблиц стилей 285 Стандарты 285 Наследование 286 Границы и заполнение текста пробелами 286 Комментарии 286 Использование стилей вдокументах 286 Определение стилей 287
Оглавление Применение стилей 288 ¦Смешивание селекторов 289 Определение старшинства стиля 290 Объекты стилей в JavaScript 290 document.tags 290 document.classes. 290 document.ids. 290 Свойства 290 Резюме 292 Глава 23. Слои 293 Универсальные действия 294 Использование таблиц стилей для создания слоев 294 Управление накладывающимися слоями 298 Создание мультипликационныхэффектов 299 <div> и <iframe> 299 Определение блоков данных 299 Вставка внешних файлов 303 <1ауег> и <ilayer> 305 Пример страницы со вкладками 305 Пример со сталкивающимися шариками 307 Резюме 310 Глава 24. Меню и панели инструментов DHTML 311 Начальные предположения 311 Выяснение возможностей 311 Планы на будущее 311 Учет API 312 Проектирование меню 312 Определение слоев 312 Обработка действий 314 Использование меню 314 Описание дополнительных возможностей 316 Создание инструментальных панелей 317 Применение событий 317 Описание проблем проектирования 318 Модульное программирование 318 Создание изображений 318 Написание HTML-кода 318 Реализация rollover-эффектов для изображений 320 Реализация поля адреса 321 Обработка событий, связанных с кнопками 322 Проверка результатов 322 Резюме 325 Глава 25. Взаимодействие с другими технологиями 326 Подключаемые модули браузера 326 Подключаемые модули и MIME-типы 326 Определение устанавливаемых подключаемых модулей 327 Элементы управления ActiveX 328 Понятие элемента управления ActiveX 328 Реализация защиты 329 Доступ с помощью JScript 329 Java-аплеты 330 Доступ к Java из JavaScript 330 Доступ к JavaScript из Java 331 Подробнее о Java-аплетах 335 LiveAudio 336 Использование JavaScript-методов 337 Воспроизведение звуков в ответ на JavaScript-события 337 Резюме 339 Часть V. Избранные программные технологии 340 Глава 26. Гарантия работы сценариев в браузерах Netscape и Microsoft 341 Версии языка и версии браузера 341 Сравнительный анализ JavaScript-диалектов 342 JavaScript от Netscape 342 JavaScript 1.0 342 JScript от Microsoft 348 Ошибки 353 Резюме 354 Глава 27. Методы выяснения типа браузера 355 Подход "Все или ничего" 355 Подход "Выяснение по месту" 355 1 Тип браузера 356 Версия браузера 356 Версия JavaScript 356 Платформа операционной системы 356 Пример динамического позиционирования 356 Резюме 359 Глава 28. Навигация по сайту с использованием JavaScript 360 Исследование технологий навигации 360 Создание сценария для динамической инструментальной панели 360 Создание объекта Toolbar 361 Обсуждение дополнительных возможностей 365 Использование объекта History. 365 Резюме. . . . ....366
JavaScript. Энциклопедия пользователя Глава 29. Формы и верификация данных 367 Установка пользовательской обратной связи 368 Создание формы для обратной связи пользователем 368 Тестирование пользовательской формы 369 Вывод окон сообщений 370 Использование сообщения о состоянии 372 Верификация данных, введенных пользователем 373 Верификация ввода данных в форму. 373 Обеспечение согласованности 373 Обеспечение бизнес-правил 374 Лроверка на завершенность 375 Создание интерактивных форм 376 Использование вычисляемых полей 377 Создание повторно используемого кода верификации 378 Целые числа 378 Строки 379 Денежные значения 379 Кредитные карточки 380 Пример: тестер цветов JavaScript 381 Резюме 384 Глава 30. Персонализация и динамические страницы 386 Статические Web-страницы 386 Немного о cookie-наборах 387 Преимущества cookie-наборов 387 Ограничения и недостатки cookie-наборов 387 Мифы о cookie-наборах 388 Использование cookie-наборов 388 Получение значений cookie-наборов 389 Установка значений cookie-наборов 389 Удаление cookie 391 Пример применения cookie-набора 391 Серверы и браузеры, поддерживающие механизм cookie-наборов 398 Другие способы поддержки информации о состоянии 398 Строка запроса 398 Скрытые переменные формы 400 Резюме 400 Глава 31. Выполнение поиска по шаблону с использованием регулярных выражений 401 Создание регулярных выражений 401 .Конструктор RegExpO 401 Оператор присваивания 401 Синтаксис регулярных выражений 401 \wm\W 402 \sm\S 402 \dn\D 402 [\Ь] 403 Точка 403 [...]иГ-1 403 [х-у] и [-х-у1 403 {х,у},{х,}и{х} 403 ?, + и* 403 Логическое или (|) 403 {...) 403 \х 403 - 4ОЗ $ 404 \Ьи\В 404 Использование регулярных выражений 404 Тестер регулярных выражений 405 .Пользовательский интерфейс 406 Функция поиска 406 Функция замены 406 Функция очистки 406 Пример: программа проверки правильности ввода телефонных номеров 407 Резюме 408 Глава 32. Технология обработки данных со стороны клиента 409 Определение источника данных: клиент или сервер? 409 Что такое клиентская таблица? 410 Создание таблиц поиска 410 Создание поискового пользовательского интерфейса 411 Обработка поисковых запросов 412 Отображение результатов поиска 413 Запуск приложения 414 Резюме 419 Глава 33. Обработка ошибок 420 Типы ошибок 420 Синтаксические ошибки 420 Ошибки времени выполнения 421 Логические ошибки 421 Интерпретация сообщений об ошибках 421 Исправление кода 422 Проверка кода HTML 422 Использование комментариев для идентификации проблем 422
Оглавление Использование метода alert() для трассировки кода 423 Тестирование кода 423 Программирование с использованием устойчивыхтехнологий 425 Высокоуровневая разработка кода проекта и детальное проектирование 426 Написание модульного кода 426 Написание сильно связанного кода 426 Написание слабо связанного кода 426 Написание повторно используемого кода 426 Написание кода обработки ошибок 426 Использование жестких соглашений по именованию 427 Использование комментариев 427 Объявление и инициализация переменных 428 Надежная работа кода 428 Резюме 428 Глава 34. Отладка 429 Использование отладчика сценариев Microsoft 429 Обзор возможностей отладчика сценариев Microsoft 429 Использование отладчика сценариев Microsoft для отладки файлов 430 Заключительные слова об отладчике сценариев Microsoft 433 Использование JavaScript-отладчика Netscape 433 Исследование возможностей J avaScript-отладчика Netscape 433 Использование JavaScript-отладчика Netscape для отладки файлов 433 Заключительные слова о JavaScript-отладчике Netscape 435 Использование метода alert() 435 Разбор примера 436 Итоговые слова об использовании метода alert() 437 Резюме .. ...437 Глава 35. JavaScript и безопасность в Web 438 Концепции безопасности в клиентской части JavaScript 439 Атаки на службы 441 Проблемы Netscape Navigator 2.0 441 Более поздние версии Navigator 442 Internet Explorer 3.x 443 Максимизация надежности защиты 443 Безопасные сеансы и цифровые сигнатуры 443 Отключение языков создания сценариев в браузере 444 Фильтрация через брандмауэр 445 Информационные ресурсы о безопасности для JavaScript и Java 445 Концепции безопасности в серверной части JavaScript 446 Java и безопасность 447 Компоненты защиты 448 Ограничения защиты 449 Резюме 450' Часть VI. Приложение 451 Приложение А. Десять основных ресурсов в Web, посвященных JavaScript 452 Netscape DevEdge Online 452 Технологии написания сценариев Microsoft 452 Введение в JavaScript от Voodoo 452 lrt.org 452 Focus on JavaScript 452 SuperScripter 453 JavaScripts.com 453 JavaScript Source 453 Webcoder.com 453 Website Abstraction 453 Сопровождающий CD-ROM 454 Предметный указатель 455
Об авторах Автор Аллеи Вайк (Allen Wyke) из Дьюрема, шт. Северная Ка- Каролина, является главой отдела технологий в Engage Technology. Упомянутая компания занимается реклам- рекламным и PR-бизнесом, повсеместно применяя при этом ведущие Internet-технологии. Аллен Вайк создавал Web- страницы для интрасетей ведущих сетевых компаний и разрабатывал множество Web-сайтов. Он программиро- программировал практически на всех доступных языках и средах, в частности C++, Java, Perl, Visual Basic, JavaScript и Lingo. Среди достижений Аллена — соавторство в книгах Pure JavaScript, The Perl 5 Programmer's Reference, The Official Netscape Navigator 4 Book, а также в книге для вы- выпускников колледжей, которая посвящена использова- использованию Internet. Аллен Вайк немало потрудился над двумя другими книгами, посвященными разработке Web-стра- Web-страниц: HTML Publishing on the Internet, Second Edition и The HTML 4 Programmer's Reference. В свободное время он пишет статьи в специальную колонку "Webmaster" ("Web- мастер") для ежемесячного журнала Sun World и ежене- еженедельно обновляет статью "Windows and UNIX Integration" ("Интеграция Windows и Unix") на сайте ITworld.com. Соавторы Ричард Вагнер (Richard Wagner) — вице-президент ком- компании Product Development for Acadia Software Infuse. Кроме того, он был главным архитектором продукта Acadia Infuse, визуального редактора JavaScript, который вскоре купила компания Net Objects. Помимо авторства во множестве книг в области компьютерных технологий, к его заслугам можно причислить создание клиент-сер- клиент-серверных и Web-приложений. Вагнер — научный редак- редактор в журнале Delphi Informant, где ежемесячно для его статей выделяется отдельная колонка "File | New", посвя- посвященная проблемам разработки программного обеспече- обеспечения. Вагнер написал Inside Paradoxfor Windows (все ре- редакции), CompuServe Internet Tour Guide и Inside CompuServe (все редакции). Он выступил в качестве со- соавтора в книгах Ultimate Windows 3.1, Inside Windows NT, Inside Microsoft Access, Inside dBASEfor Windows я Integrating Windows Applications. В Тейлорском университете Ричард получил ученую степень бакалавра гуманитарных наук в области политологии, после чего защитил диплом в Американском университете. Он доступен по адресу: rwagner @acadians. com. Джейсон Джиллиам (Jason D. Gilliam) — разработчик программного обеспечения в K0Z.com, подразделении компании Research Triangle Park (шт. Северная Кароли- Каролина). Джейсон создал множество Web-страниц, а также не меньшее количество приложений на языке C++, ком- коммерческих Web-приложений и программ для связи с базами данных. Он начал программировать в тринадцать лет, а сейчас является соавтором книги Pure JavaScript. В Государственном университете Северной Каролины он получил степень бакалавра в области компьютерной инженерии. В свободное время Джейсон разрабатывает аудиопрограммы на базе Windows и сочиняет музыку на ПК. Фрэнсис Ботто (Fransis Botto) родился в Свэнси (Уэллс, Великобритания). Свою карьеру он начал в ка- качестве автора и исследователя в области новых техноло- технологий. С середины 80-х годов Фрэнсис известен как один из первых составителей статей и книг, сохранивших свою актуальность до сих пор. Сначала они издавались в Великобритании, после — в Австралии. По сути, его работа затрагивает сферу пользователя, разработчика и вопросы концептуального проектирования. Накоплен- Накопленным опытом Фрэнсис Ботто любезно поделился с чита- читателями в этой книге. Посвящения Все написанное мною — для Мэтта, Джеффа и Грэга. Ребята, вы не только прекрасные друзья, но и самые лучшие мужья, найденные моими сестрами. — Аллен Вайк Благодарности Сначала мне хотелось бы поблагодарить Боба Керна (Bob Kern) из издательства TIPS Publishing и моих соавторов: Ричарда, Джейсона, Фрэнсиса за их профессионализм, тяжелый труд и всяческую поддержку во время написа- написания этой книги. Я весьма благодарен Шелли Джонстон (Shelley Johnston), проявившей себя в качестве талант- талантливого и незаменимого редактора, что помогло нам сконцентрировать все внимание на работе над книгой. Наконец, мне хотелось бы поблагодарить Кимо "Кинг" Конга (Kimo "King" Kong) за предоставленную возможность писать книгу во время работы в Engage, — Аллен Вайк
Введение JavaScript в рекордные сроки стал средством разработки для Web, будь то простое усовершенствование HTML- страниц, либо создание полнофункциональных Web- приложений. С другой стороны, Javascript никогда не станет столь же популярным, как Java или даже HTML. Однако следует учесть, что JavaScript может обеспечи- обеспечивать ряд вещей, совершенно не характерных для других языков программирования, самой главной из которых следует считать эффективное совместное функциониро- функционирование абсолютно различных технологий. К JavaScript вполне применима метафора "мастер на все руки"; она- то, собственно, и отражает всю неисчерпаемость этого языка. Большинство рассматривает JavaScript как клиентс- клиентский язык. Истинная правда! Многое в данной книге сфокусировано на внедрении JavaScript в HTML с це- целью обеспечения работы в среде, поддерживающей бра- браузерами. Однако JavaScript также известен и как сервер- серверный язык сценариев. До недавнего времени одними из первых продуктов, в которых в качестве языка сценариев для Web использовался JavaScript, были Netscape's Server-Side JavaScript (SSJS) и Microsoft's Active Server Pages (ASP). Ваш покорный слуга является разработчиком, и чем чаще он использует JavaScript, тем больше отмечается его пригодность для приложений, создаваемых компанией. Надеюсь, что способность JavaScript выполнять множе- множество задач станет для читателей очевидным. А сейчас самое время перечислить все темы, рассмотренные в книге: • Что связывает между собой JavaScript и HTML? • В чем разница между JavaScript и Java? • Существует ли какая-либо совместимость между вер- версиями JavaScript и JScript? Какие спецэффекты можно создать при помощи JavaScript? • Как создать интеллектуальные фреймы с помощью JavaScript? • Что такое базовые объекты JavaScript? • Где применяется ECMAScript? • Как JavaScript совмещается с элементами управления ActiveX, программными расширениями и Java-апле- тами? ¦• Как JavaScript поддерживает текущее состояние? Как использовать JavaScript на собственном Web-сер- Web-сервере? Как при помощи JavaScript подключиться к базе дан- данных SQL? Кому адресована эта книга? Поскольку JavaScript — основной язык сценариев для Web, то он используется при решении задач различного рода. Вот лишь небольшой перечень тех, кто применяет JavaScript: Web-мастера, HTML-дизайнеры, разработчи- разработчики Java-приложений, разработчики приложений баз дан- данных, опытные пользователи. Я уверен, что читатели, относящиеся к любой из этих категорий, по достоинству оценят книгу. Предполагает- Предполагается, что читатель обладает базовыми знаниями Web-тех- Web-технологий и HTML. Какой-то первоначальный опыт ра- работы с JavaScript не нужен, однако определенные знания в области программирования на языке сценари- сценариев все же не помешают. С другой стороны, если вы никогда раньше не составляли программ, это вовсе не означает, что данная книга — не для вас. Стоит лишь помнить, что книга не рассчитана на совершенно начи- начинающих, поэтому таковым будет не настоль комфорт- комфортно, как тем, кто обладает определенным опытом. В осо- особенности последнее касается некоторых главах, посвященных серверам и базам данных, где базовые знания обязательны. Все же, набравшись терпения, на- начинающие программисты смогут успешно изучить эту книгу и приступить к самостоятельной разработке се- серьезных бизнес-приложений для Web. Системные требования Для работы с JavaScript потребуется компьютер с дос- доступом в Internet. Авторы книги использовали Windows (98, 2000, NT), но те же механизмы, касаемые JavaScript, актуальны и для других платформ (за исклю- исключением лишь тех, для которых отдельно указано, что JavaScript на них не поддерживается). Структура книги Третье издание книги — всестороннее описание JavaScript и соответствующих технологий. Книга разде- разделена на шесть частей, в конце каждой из которых при- приводится краткое резюме. Часть 1 Знакомство с JavaScript Часть 1 — всестороннее знакомство с JavaScript и соот- соответствующими инструментальными средствами. В главе 1 внимание фокусируется на связи между JavaScript и разработкой Web-приложений. Кроме того, исследует- исследуется связь JavaScript с другими Web-технологиями как со стороны клиента, так и со стороны сервера. О взаимо- взаимосвязи между HTML и JavaScript, а также об интерпре- интерпретировании кода браузером в рабочей среде, можно будет узнать из главы 2. В главе 3 рассматриваются инстру-
JavaScript. Энциклопедия пользователя ментальные программные средства, требуемые для про- процесса разработки в JavaScript. В главе 4 описывается пол- полный процесс составления первого учебного сценария. Часть 2 Базовое подмножество языка JavaScript Здесь подробно рассматривается собственно язык JavaScript. Главы с 5 по 12 посвящены основам языка, операторам, управляющим структурам, функциям и объектам (базовым, клиентским, серверным и пользова- пользовательским). Часть 3 Использование DOM В части 3 подробно исследуется проблематика Document Object Model (объектная модель документов). Будет рас- рассмотрен метод размещения элементов на странице, а также обработка событий (глава 14). Наконец, главы с 15 по 19 содержат подробную информацию по объектам Window, Document, Form, Frame и другим DOM-объек- DOM-объектах. Часть 4 Технологии программирования на динамическом HTML В части 4 внимание уделяется различным операциям, которые выполняются с помощью JavaScript в среде Web. В главе 21 рассказано о создании анимации, баннеров и других спецэффектов в JavaScript (без использования каких-либо Java-аплетов). Глава 22 посвящена каскади- каскадированным таблицам стилей, а глава 23 — слоям, появив- появившимся в четвертом поколении браузеров. В главе 24 вся информация собирается воедино и демонстрируется методика создания динамических НТМГ-меню и пане- панелей инструментов. Часть 4 завершается главой 25. В ней исследуются возможности взаимодействия JavaScript с другими технологиями, наподобие Java и ActiveX. Часть 5 Гарантия работы сценариев в браузерах Netscape и Microsoft Часть 5 построена именно на том, что интересного чи- читатель смог вынести из области разработок на JavaScript. Глава 26 учит, как создавать сценарии, работающие с браузерами Navigator и Internet Explorer. В главе 27 под- подробно описывается методика определения браузера, а глава 28 подскажет, что может предоставить JavaScript в плане совершенствования навигации Web-сайтов. Гла- Глава 29 содержит информацию об усовершенствовании НТМГ-форм с помощью JavaScript, например, за счет добавления проверки достоверности данных со стороны клиента. В главе 30 обсуждаются вопросы создания ди- динамических и персонализированных web-страниц за счет применения cookie-наборов и других средств сохранения состояния. В главе 31 представлено сопоставление образ- образцов в регулярных выражениях, а в главе 32 — способы сбора и обработки данных. И, наконец, глава 33 посвя- посвящена обработке ошибок, а глава 34 дает краткие сведе- сведения об отладке JavaScript-приложений. Книга заверша- завершается главой 35, в которой обсуждаются вопросы безопасности в JavaScript. Часть б Приложение В приложении А перечислены Internet-ресурсы для JavaScript. Здесь представлены URT популярных и по- полезных сайтов, которые помогут лучше разобраться в JavaScript. Соглашения, используемые в книге В книге использованы соглашения, призванные улуч- улучшить восприятие материала: • Листинги программ на JavaScript приводятся моноши- моноширинным шрифтом. • Имена методов JavaScript, выводимые на экран сооб- сообщения приводятся полужирным шрифтом. • Заполнители (слова, подставленные вместо того, 4'iо необходимо набирать на клавиатуре) выделяются полужирным курсивом. • Вновь вводимые термины выделяются курсивом. • Пункты меню отделяются друг от друга запятыми, на- например: "Выберите File, Open" означает необходи- необходимость открыть меню File и в нем выбрать элемент Open. • Иногда код JavaScript не вмещается в одну строку. Для его продолжения на следующей строке используется знак "стрелочка" (*¦*). Кроме того, в книге использованы специальные вы- выделения. Они включают в себя: Примечание, Совет, Предупреждение, Внимание, Ресурс, Напоминание,
Знакомство с JavaScript ЧАСТЬ Я* ' 1Я*' * I , „ > k -. i. 2. 3. 4. В ЭТОЙ ЧАСТИ JavaScript и World Wide Web Совместная работа JavaScript и HTML Создание собственного набора инструментальных средств JavaScript Создание первого сценария -¦?¦
JavaScript и World Wide Web В ЭТОЙ ГЛАВЕ Знакомство с JavaScript Десять заповедей JavaScript, которые должен знать каждый создатель сценариев Четыре фазы развития World Wide Web Среда разработки Web-приложений Что можно сделать при помощи JavaScript? Сравнение JavaScript и VBScript Как известно, один Internet-год эквивалентен трем месяцам календарного года. Учитывая это, самой полез- полезной рекомендацией для читателей будет изучение JavaScript, что поможет пробиться в первые ряды разра- разработчиков. Конечно, к этому можно относиться, как к игре, но для полного понимания работы JavaScript по- потребуется полностью изучить всю информацию. И как в любом деле, необходимо бросить все усилия на переработку информации и понимание приведенных ниже примеров. Перед углублением во все винтики механизма созда- создания программ на JavaScript следует разобраться, какова же цель создания этого языка. JavaScript уже давно вы- вышел за первоначально планируемые пределы отдельно взятого браузера. Сейчас его можно найти на серверной части, а также вместе с последним выпуском операци- операционной системы Windows. Вариант JavaScript на сторо- стороне браузера ограничен также, как и другие Web-техно- Web-технологии: HTML, Java, CSS и подключаемые модули (plug-ins). JavaScript проявляет себя как исключитель- исключительно мощное средство, взаимодействующее с другими тех- технологиями для создания эффективных и обдуманных решений. В этой главе предлагается небольшой обзор JavaScript вместе с кратким анализом среды разработки Web-при- Web-приложений. После этого будут подробно рассмотрены сферы использования JavaScript, текущая поддержка JavaScript в браузерах, а также некоторые отличитель- отличительные черты JavaScript и VBScript. Знакомство с JavaScript Как и все, что связано с Web, новая технология JavaScript гораздо моложе Java. JavaScript сначала был разработан компанией Netscape, поэтому его первое имя — LiveScript. Ожидалось, что этот язык сценариев расширит возмож- возможности HTML и выступит в качестве частичной альтер- альтернативы большому числу CGI-сценариев, будет перера- перерабатывать информацию из формы и добавлять динамику в пользовательские страницы. После выхода Java ком- компания Netscape начала работать вместе с компанией Sun над созданием языка сценариев, чей синтаксис и семан- семантика по плану должны были тесно связываться с Java. Отсюда возникло и название JavaScript. В результате совместных усилий Netscape и Sun и был создан этот язык. Одна из причин, послуживших созданию JavaScript, была связана с потребностью в присутствии логики и интеллекта не только со стороны сервера, но и клиен- клиента. В этом случае все выполнение переходит к серверу, причем даже такие простые операции, как проверка допустимости данных. Фактически, при отсутствии логики на стороне клиента Web-среда превращается в устаревшую хост-терминальную архитектуру, вытеснен- вытесненную революцией ПК в 80-х годах. Внедрение логики в браузер существенно усилило клиента и превратило отношение в истинную клиент-серверную систему. Java — один из шагов в нужном направлении, одна- однако Java была внедрена в виде дополнения HTML, и никто не собирался интегрировать Java с языковой точки зрения. Хотя Java — строго типизированный язык, он не подходит для сращивания большого количества тех- технологий, необходимых Web-мастерам при создании Web-страниц. Более того, программирование на Java не требует весьма серьезных знаний и опыта. Поэтому многие разработчики HTML отказываются от работы, состоящей лишь в реализации логики для элементов
JavaScript И World Wide Web формы. Клиентский язык сценариев высокого уровня казался утерянным звеном на арене Web-технологий. С момента своего появления (декабрь 1995 г.) язык JavaScript имел существенную поддержку в лице веду- ведущих производителей, в числе которых Apple, Borland, Sybase, Informix, Oracle, Digital, HP и IBM. JavaScript продолжает развиваться, внедряясь не только в совре- современные браузеры, но и в приложения, созданные раз- различными компаниями. Идея начала скудеть, даже когда присоединилась компания Microsoft. Понимая всю важность создания Web-сценариев, Microsoft решила поддержать JavaScript. Однако компания Netscape предпочла передать Microsoft лишь только лицензию на право использова- использования технологии. На основе общедоступной документа- документации в Microsoft был создан "перепроектированый" JavaScript — JScript, поддерживаемый Internet Explorer 3.0 и выше. JScript 1.0 плохо совместим с JavaScript 1.1, используемым Netscape Navigator 3.0 и более поздни- поздними браузерами. В конечном итоге мириады версий и различных хитростей, характерных для того или иного браузера, стали причиной головной боли для разработ- разработчиков Web-сайтов, использующих JavaScript (см. главу 26). В главе 27 можно найти более подробную инфор- информацию о работе с различными версиями JavaScript. К. счастью, огорченные разработчики сценариев смогли вздохнуть свободно. Компании Netscape, Microsoft и другие производители решили подогнать язык под стандарты ЕСМА (European Computer Manufacturer's Association). В тот период ЕСМА соста- составила спецификацию языка — ECMAScript, что поддер- поддержали все производители. Хотя стандарты ЕСМА оказы- оказывают существенную помощь, все же компании Netscape и Microsoft продолжают развивать языки JavaScript и JScript, выходя при этом за пределы стандартов. Помимо JScript, еще одним конкурентом JavaScript является VBScript, созданный с целью упрощения Web- разработок на Visual Basic (VB). VBScript является подмно- подмножеством языка Visual Basic. Из-за отсутствия поддержки со стороны Netscape, VBScript используется для интрасе- тей (или Internet-сайтов). Он пользуются большой попу- популярностью у пользователей Microsoft Internet Explorer. Листинг 1.1 Внедрение JavaScript в HTML-файл Глава 1 Несмотря на появление VBScript, JavaScript стал стандартным языком сценариев для Web. JavaScript ча- часто применяется при создании инструментов для раз- разработки Web-страниц. На стороне сервера Netscape ис- использует язык, на который часто ссылаются как на Server Side JavaScript (SSJS). Но к этому мы вернемся немного позже, в главе 12. Разумеется, компания Microsoft сочла необходимым минимизировать отстава- отставание, выпустив технологию Active Server Pages (ASP), поддерживающую JScript. Десять заповедей JavaScript, которые должен знать каждый создатель сценариев Изучение JavaScript может оказаться сложной задачей. Все основы объединены в 10 "заповедей". Они призва- призваны оказать помощь при овладении JavaScript. Перед началом работы с языком внимательно изучите их. JavaScript можно внедрить в HTML "Бракосочетание" между JavaScript и HTML стало, воз- возможно, одним из важнейших событий. При работе с JavaScript на клиентской части можно убедиться, что эта парочка поистине неразлучна. Программы JavaScript обычно заключены в HTML-документах, и выполняют- выполняются в них же. Большинство объектов JavaScript представ- представлены соответствующими дескрипторами HTML, поэто- поэтому код находится на уровне клиентской части языка. Чтобы стать настоящим разработчиком на JavaScript, следует досконально изучить HTML, HTML используется в JavaScript как мостик к тому, что называется средой разработки Web-приложений. Воз- Возможности HTML расширяются за счет обеспечения дескрипторов HTML событиями и организации управ- управляемой событиями среды выполнения. Позже об этом рассказывается более подробно. В ли- листинге 1.1 приводится пример внедрения кода JavaScript в исходный код HTML. Серым выделен текст на JavaScript. Все остальное — простой HTML. <html> <head> <title>Status Bar</title> <seript fcypea>!text/5a.vaso < ! — window, defaultstatus « "Welcome to the large URL page." function changes tatus () { window, status = "Click me to go to the Unleashed home page. function changeDefaiiltStatus () { window, detaultstatiis = window, document;
Знакомство с JavaScript Часть I ""•options [window, document. stattisForni.messageList. selectedlndex] . t </script> </head> <body> <p>S#160;</p> <p>K#160;</p> <p align="center"> <font size= <strong>http //www. samspublishing . oom</strong> </fant> <p align="center"> <a href="http: //www.samspublishiiKj.com" onmouseover=!;changeStatus() ;return true"> Go...</a> <p align=center> <font size="l"> To change the default status bar message, select a message from the list below and click the Change button. </font> <?orm name="statusForm" method="POST"> <select name="messageList" size="l"> <cpticn selected>Welcome to the large URL page.</option> <option>On route to Sams Publishing</option> <option>This page intentionally left (nearly) blank. </option> <option>An exciting example of changing status bar text. </cptian> </select> <input type="button" name: onclick="changeDefaultStatus ()"> </form> </body> </html> ПРИМЕЧАНИЕ Готов держать пари, что вы обратили внимание на type="text/javascript". Действительно, новые стандар- стандарты HTML и XHTML отказались от языкового атрибута в дескрипторе <script>. He стоит сейчас беспокоиться, об этом будет рассказываться в следующих главах. JavaScript зависит от среды JavaScript — язык сценариев, а не инструмент. Про- Программное обеспечение, собственно выполняющее код на — это механизм интерпретации внутри сре- среды, к которым относятся браузеры Netscape Navigator, Microsoft Internet Explorer, а также один из серверных механизмов. После включения в документы HTML JavaScript начинает зависеть от браузера (рис. 1.1). Если же поддержка со стороны браузера отсутствует, тогда ваш код выполняться не будет. Более того, если пробле- проблема поддержки браузером решена не будет, код просто высветится на странице как текст (рис. 1.2) (см. главу 2, где детально описываются способы предотвращения вывода кода на экран). MacOSX Thenca-generation operating system. РИСУНОК 1.1 Microsoft Internet Explorer 4.5ппдд JavaScript Очень важно помнить об этой взаимосвязи, если необходимо использовать JavaScript для создания при- приложений. Будет ли принято во ннима! : что потребу-
JavaScript u World Wide Web ется браузер, поддерживающий JavaScript? Если так, то будет ли организовано уведомление пользователей об этом? Будет ли создаваться версия, не использующая JavaScript? При разработке приложений на JavaScript потребуется ответить на все эти вопросы. РИСУНОК 1.2. Mosaic не поддерживает JavaScript ПРИМЕЧАНИЕ Сразу же после своего появления фреймы оказались новинкой. Их можно было просматривать только с по- помощью Netscape Navigator 2.0. Авторы HTML должны были решить, как использовать фреймы и что делать в случае, когда браузер их не поддерживает. Их популяр- популярность существенно возросла в результате поддержки нией Microsoft в Internet Explorer 3.0, после чего фреймы стали частью стандарта HTML 4. При использо- использовании HTML 4 вам обеспечивается браузер, поддержи- вающийфреймы. 'К счастью разработчиков JavaScript, это та же поддер- поддержка, что и для JavaScript. Netscape Navigator 2.x, пос- после — Microsoft Internet Explorer 3.x, затем — Opera 3.x, а потом — 95% существующих браузеров, поддержива- поддерживают JavaScript. Если данная тенденция будет и дальше раз- развиваться, то зависимость от браузеров станет менее зна- значительной. ¦ JavaScript - интерпретируемый язык Как и большинство языков сценариев, JavaScript интер- интерпретируется браузером. JavaScript не компилируется в 'бинарный код наподобие .ехе, но все же остается час- частью документа HTML. Недостаток интерпретируемого языка — для выполнения кода затрачивается много вре- времени, поскольку браузер компилирует директивы во время выполнения. Однако есть и преимущество - можно легко и быстро усовершенствовать исходный код. Не переживайте по поводу старых версий сценариев JavaScript. Если вы замените их в исходном документе HTML, то новый код будет выполняться при каждом получении пользователем доступа к документу. Глава 1 Небольшая оговорка: разработка на JavaScript, харак- характерная для Netscape, на стороне сервера потребует ком- компиляции всех файлов JavaScript и HTML в байт-код, сохраняемый в файлах .web. JavaScript - слабо типизированный язык JavaScript отличается от типизированных языков, таких как Java и C++, которые требуют объявления всех пе- переменных определенных типов перед началом их ис- использования. JavaScript, наоборот, очень гибок. Вы не обязаны объявлять переменные специального типа. Если специальный тип вам неизвестен, то можно рабо- работать с переменной. Последнее утверждение иллюстри- иллюстрируется фрагментом кода. Например, требуется объявить переменную myVal, присвоить ей строковое значение и отобразить ее в окне сообщений. Можно воспользовать- воспользоваться следующим кодом: function flexible () ( var myVal // объявляем переменную myVal mVal = "Pi" // присваиваем myVal некоторое // значение alert (itYVal) // используем ее i Хотя явное объявление переменных и отражает хо- хороший тон программирования, вовсе не обязательно проделывать это. Следующий код, прекрасно функци- функционирующий в JavaScript, окажется просто немыслимым в типизированных языках. function flexible () { mVal = "Pi" // устанавливаем значение // необъявленной переменной myVal alert (iryVal) // используем ее I Следующий пример продемонстрирует всю гибкость языка JavaScript — можно изменить тип значения, пред- представляемого переменной. Например, переменная myVal в процессе выполнения функции изменяет строковое значениеначисленное: function flexible () ( var myVal = "Pi" alert (myVal) myVal = 3.14159 alert (myVal) Javascript -- объектно-ориентированный язык Netscape и другие компании отнесли JavaScript к объек- объектно-ориентированным языкам (OOP — object-oriented programming). Как упоминается в главе 9, JavaScript дей- действительно является объектно-ориентированным языком. Вы работаете с объектами, которые инкапсулируют данные (свойства) и поведение (методы). (Если вы уже
Знакомство с JavaScript Часть I пользовались точечной нотацией, скажем, в Visual Basic, Java или Delphi, вам не составит особого труда овладеть JavaScript.) Однако, хоть и можно работать с объекта- объектами, их невозможно разделить на подклассы. Объектная модель JavaScript основывается на экземплярах, а не на концепции наследования. JavaScript - язык, управляемый событиями Большинство составленных кодов будет отвечать на события, генерируемые пользователем или системой. Язык JavaScript обладает поддержкой обработки собы- событий. HTML-объекты, подобные кнопкам и текстовым полям, усовершенствованы с целью поддержки обра- обработчиков событий. При переходе к JavaScript из Java или Visual Basic, эта управляемая событиями среда яв- является второй натурой. При переходе от процедурной среды, от среды нисходящего проектирования, потре- потребуются отдельные знания, связанные с управлением событиями. В главе 14 подробно описываются собы- события JavaScript. JavaScript - это не Java Путешествуя по просторам Web, читатель мог встретить фразу: "JavaScript — это не Java". Как обсуждалось ра- ранее, Java и JavaScript разрабатывались разными компа- компаниями. Основная причина сходства имен кроется в мар- маркетинговых соображениях. Мы углубимся в различия между JavaScript и Java в главе 5, однако сейчас будет не лишним кратко посмотреть на основные различия и сходства этих двух языков. Во-первых, JavaScript тесно интегрирован в HTML, а Java-аплеты всего лишь связываются с HTML-доку- HTML-документами через дескриптор <applet>. Сам же аплет хра- хранится в другом файле, загружаемом из сервера. Во-вторых, Java — более надежный и функциональ- функционально полный язык, т.к. ему присущи свойства наподобие строгого контроля типов, объектной ориентации и на- наличию компилятора. Если Java предназначен для созда- создания аплетов и независимых приложений, то JavaScript — исключительно для написания сценариев. Синтаксис JavaScript напоминает синтаксис Java. Если вы привыкните к управляющим структурам JavaScript, можете считать, что первый шаг к овладению Java уже сделан. JavaScript - многофункциональный язык JavaScript — многоаспектный язык, который может при- применяться в различных контекстах для решения проблем, связанных с Web. Немного дальше в этой главе рассмат- рассматриваются сферы применения JavaScript. Основные цели, достигаемые при помощи JavaScript: Усовершенствование и оживление статических HTML- страниц с помощью спецэффектов, анимации и бан- неров. • Проверка данных без передачи на сервер. • Получение основы для разработки Web-приложений типа клиент-сервер. Разработка клиентских приложений. "Сращивание" со стороны клиента HTML-объектов, Java-аплетов, элементов управления ActiveX и под- подключаемых модулей Netscape. Получение расширения к Web-серверу. ¦• Моделирование связи с базами данных 6e's исполь- использования CGI. JavaScript - развивающийся язык Ранее в главе упоминалось, насколь современен JavaScript как технология. Учитывая резкие перемены в Web, не- несложно понять, что JavaScript продолжает свое развитие в качестве языка. При разработке приложений JavaScript требуется думать не только о том, поддерживает ли тот или иной браузер JavaScript, но еще и о том, какое имен- именно подмножество языка. Не мудрено попасть в безвы- безвыходную ситуацию, поскольку количество версий пере- перешло всякие мыслимые пределы: JavaScript — 6 версий A.0—1.5), JScript — огромное количество версий A.0—5.5 и еще несколько версий наподобие х.х.х). Посетите страницу Netscape's DevEdge по адресу http:// developer.netscape.com или Mozilla.org (область Open Source для инструментальных средств браузера Netscape) по адресу http://www.mozilla.com. Усовершенствования JScript отражаются на странице Microsoft по адресу http://msdn.microsoft.com/scripting. Сферы использования JavaScript Стоит еще раз напомнить: JavaScript — язык, а не ин- инструмент. Поскольку это — язык сценариев, его можно применять в широком диапазоне приложений. Если рас- рассматривать JavaScript в контексте разработки Web-страниц, то в большинстве своем применение касается клиентс- клиентской части. На стороне сервера JavaScript применяется в средах Netscape Enterprise Server и Microsoft Active Server Pages. Он является родным языком в наборах инструмен- инструментальных средств для разработки Web-страниц, таких как Borland Intra Builder, Macromedia Dreamweaver (начиная со второй версии). Не следует думать, что JavaScript — исключительно клиентский язык сценариев. Новейшие версии Microsoft Windows поддерживают JavaScript на рабочем столе, вместе со средой Window Script Host (WSH).
JavaScript u World Wide Web Глава 1 Четыре фазы развития World Wide Web Резкие изменения в Web-технологиях за последние шесть лет привели к бурному росту Web. Перед обсуж- обсуждением темы Web-приложений было бы полезно про- проследить эволюцию Web от простейшего "расширения" Interene: до уровня "культуры", ставшей частью совре- современной жизни. Эволюция условно делится на четыре фазы. Фаза 1. Символьный гипертекст Web появилась в 1989 г. и была текстовой гиперссылоч- гиперссылочной системой. Это ограничение легло в основу потому, что компьютеры, имевшие доступ к Web, не обладали качественным способом от ображсния графики на экра- экране. В первый период существования Web пользователи должны были вводить числа, представляющие страни- страницы, которые требовалось просмотреть. Со временем появилась возможность выбора подсвеченного текста и перехода к соответствующей странице. Гипертекстовая сущность Web приобрела революционное значение во многих областях, связанных с наукой. Фаза 2. Графически-ориентированные статические HTML-документы Вторая фаза развития Web началась в 1993 г. с появле- появления графического Web-браузера под названием NCSA Mosaic. Одним из разработчиков Mosaic был студент и будущий основатель Netscape — Марк Андерсен (Маге Anderssen). Mosaic разрабатывался для Национального центра по применению супер-ЭВМ (NCSA — National Center for Supercomputing Applications). Хотя создание Web, в основном, было направлено на удовлетворение нужд научных сообществ, возможность просмотра гра- графики существенно усилила Internet. В то время графи- графические среды приобрели гораздо большую популяр- популярность, нежели настольные символьно-ориентированные системы. Microsoft выигрывала войну операционных систем, выпустив на рынок Windows 3.1x. Графический браузер присоединился к настольной графической среде и стал именно той "изюминкой", которую так ждали. Через несколько месяцев компью- компьютерные компании стали добросовестно и целеустремлен- целеустремленно проникать в Web. Web сама по себе осталась статической (см. рис. 1.3). Содержимое включало в себя текстовые или графичес- графические документы и ряд других элементов. Возможно, стра- страница содержала аудио- или видеофайлы. Приходилось сначала загружать файл, а потом проигрывать его, ис- используя внешнее приложение. Welcome to WHkes.Net эКопе Membership Corporation's Homo Page РИСУНОК 1.3 Статическая HTML-страница Фаза 3. Динамические HTML-документы В течение первых двух фаз Web-страницы создавались при помощи текстового редактора НТМГ и помещались на Web-сервер. После размещения на сервере большин- большинство страниц оставались статическими до тех пор, пока автор их не изменял. Статические страницы вполне подходят для некоторых целей, однако не для всех. Для динамической генерации НТМГ-документов Web-разра- Web-разработчики стали использовать CGI-сценарии (CG1 — Common Gateway Interface, интерфейс общего шлюза), обеспечивая с их помощью создание НТМГ-докумен- НТМГ-документов "на лету". Как раз это и стало основой первого уров- уровня взаимодействия с пользователем в Web. С таким усо- усовершенствованием Web могла превратиться в платформу для гипертекстовых документов, и кроме того, служить средой прикладных приложений. Одним из первых Web-приложений, демонстрирующих всю мощь новых технологий, стал Web-сайт курьерской почты Fedrx (см. рис. 1.4). [ 3 FmC» I 1i***4 - HiCrO HE"*-* Express all Inlrrrel Ei(Jo=n Tracking m& Enter Up To 25 Airbill Numberi Diter ни Auiiir Nunh-i yer H**.) BKii дм I ¦rm Я I Forthe latest on serncts, CUy Г4 pftpWF fOUT shipments wtJe jWic urine Yuu can prepare Air .. л РИСУНОК 1.4. FedEx предложила одно из самых привлекательных Web-приложений
Знакомство с JavaScript Часть I Фаза 4. Активные HTML-документы Четвертая фаза развития Web началась в 1995 г. с появ- появлением подключаемых модулей (plug-ins) в Netscape Navigator и существенно ускорилась за счет внедрения поддержки Java. Необходимо было усилить клиентскую сторону и отказаться от опоры исключительно на сер- сервер при запуске приложений либо обработке информа- информации, введенной пользователем. Благодаря Java, Web более не является коллекцией документов HTML, но может быть истинной клиент- северной средой, в которой клиент обладает определен- определенной независимостью от сервера. JavaScript соответству- соответствует данным требованиям. В JavaScript, Java, ActiveX и других клиентских расширениях браузер становится мощнейшей операционной средой, в которой можно работать с Web-приложениями. Среда разработки Web-приложений Использование Web в качестве среды проектирования — относительно новое явление. С появлением Java, JavaScript, ActiveX и других технологий, идея развития Web-при- Web-приложений показалась весьма заманчивой. Web как среда проектирования может выглядеть достаточно сложной. Учитывая распределенный харак- характер Web, Web-приложения могут состоять из множества частей, в каждой из которых применяется так или иная технология. В рамках типичной клиент-серверной архитектуре на базе локальной сети могут существовать клиентские приложения, подключенные к сетевому серверу баз дан- данных. Зачастую клиентское приложение разрабатывает- разрабатывается с использованием единственного инструмента, ска- скажем, Delphi или Visual Basic. Как правило, серверная часть приложения разрабатывается и поддерживается с помощью инструментальных средств администратора SQL Server. На рис. 1.5 показаны элементы, составляющие сре- среду разработки приложений. Далее каждый из этих эле- элементов будет рассматриваться более подробно. Среда разработки web-приложений — реальный при- пример того, что сумма гораздо лучше, чем отдельно взятые части. создание содержимого браузеры Microsoft Internet ЕкрЬгег клиентские расширения РИСУНОК 1.5. Среда разработки Web- приложений серверы серверные расширения расширения баз данных написание сценариев безопасность управление содержимым База данных Службы
JavaScript U World Wide Web Сама по себе каждая из этих технологий ограниче- ограничена и довольно узка в своей области. Но когда эти части увязываются в единое приложение, повышается эффек- эффективность средств для развития Internet и интрасетевых решений. Клиентская часть Клиентская часть среды разработки Web-приложений состоит из 4-х строительных блоков: • Браузеры HTML (Hypertext Markup Language, язык гипертек- гипертекстовой разметки) • Клиентские расширения (Java-аплеты, элементы уп- управления ActiveX и подключаемые модули Netscape) • Языки сценариев (JavaScript и JScript) Ниже кратко рассматривается каждая из технологий, а также их совместная работа. Рисунок 1.6 отражает отношения между ними. Браузеры Без сомнений, самая главная часть Web-приложения — браузер. Браузер — окно в Web для пользователей и служит пользовательским интерфейсом для вашего при- приложения. Технология браузеров довольно-таки проста (чтение HTML и вывод на экран), но появление нестан- нестандартных усовершенствований, наподобие JavaScript и Глава 1 слоев Netscape, делает критическим выбор браузера во время определения платформы разработки. При создании приложения для интрасети несложно убедиться, что все пользователи применяют стандарт- стандартный Web-браузер. Однако при создании Internet-прило- Internet-приложения для пользователей со всего мира вопросы проек- проектирования приобретают более сложный характер, с перевесом функциональных возможностей по отноше- отношению к совместимости. Таблица отражает ситуацию с двумя основными на сегодняшний день браузерами. HTML HTML — один из кирпичиков, лежащих в основе Web. HTML — язык гипертекстовой разметки, создающий структуру и обеспечивающий форматирование простого текстового файла. Как "технология", он довольно рутин- рутинный; некоторые даже заявляют, что он устаревший. Од- Однако именно эта общность и наделяет язык силой. Несмотря на то что браузер обеспечивает пользова- пользователю окно для отображения Web-содержимого, само> содержимое поступает в форме текста HTML. He име- имеет значения, представляются ли статические докумен- документы, возвращается результат запроса, обрабатывается форма обратной связи или же выводится результат ра- работы JavaScript-приложения. Какими бы ни были мето- методы получения этих данных, для их отображения все пре- превентивно переводится в дескрипторы HTML. Подключаемые модули РИСУНОК1.& Клиентскаячасть Браузер HTML <html> <head> <title>Untitled Normal Page</ title> <SCRIPT LANGUAGE "JavaScript"> function confirmAction(callingObject) { return con?irm("Do you really want this subscription? The magazine is not really that good.") </SCRIPT> </head> <body> Аплеты элемент управлении ActiveX Языки сценариев Таблица 1.1. Поддержка клиентских технологий со стороны современных браузеров Netscape Navigator Microsoft Internet Explorer Поддержка JavaScnpt/JScnpt Поддержка VBScript Поддержка Java Поддержка ActiveX Подключаемые модули Netscape 2.0+ Отсутствует 2.0+C.0+для Mac) 3.0+ (подключаемый модуль) 2.0+ 3.0+ 3.0+ 3.0+ 3.0+ 3.0+
Знакомство с JavaScript Часть I Клиентские расширения По мере возрастания потребностей в активных Web- страницах, простое расширение браузеров уже не мог- могло рассматриваться в качестве удобоваримого решения. Некоторые расширения были подключаемыми модуля- модулями независимых разработчиков, которые увеличивали эффективность браузеров. Однако появилась потреб- потребность работать с выполняемым содержимым (executable content) в самом браузере. Для самой технологии не обя- обязательно привязываться к работе конкретного браузера, хотя он и поддерживает ее. На сегодняшний день существуют три отдельных клиентских расширения. У них есть общие черты, рав- равно как и отличия: • Java-аплеты Элементы управления ActiveX • Подключаемые модули Netscape Java-аплеты Если вы никогда не слышали о языке программирова- программирования Java, вас вполне могут назвать Митрофанушкой. О Java говорилось гораздо больше, чем о любом другом языке программирования. Хотелось бы рассказать о нем в контексте среды разработки Web-приложений. __ __ РЕСУРС : .. . .Информация по Java находится на сайте компании Sun по адресу http://java.sun.com. :-:¦! Java — независимый от платформы язык программи- программирования, разработанный компанией Sun Misrosystems. Изрядно говорилось о возможности Java создавать со- содержимое, выполняемое на подавляющем большинстве платформ. Внутри среды браузера Java-программы называются аплетами (applets). Связь с аплетом осуществляется че- через дескриптор <applet> в документе HTML, в резуль- результате чего аплет может быть загружен на клиентский компьютер. Аплет поступает в браузер в виде последо- последовательности байт-кодов. Если Java браузером поддержи- поддерживается, байт-код интерпретируется и выполняется на клиентской машине. Ссылки на Java-аплеты Java-несо местимыми браузерами игнорируются. шетьг используются в нескольких сферах. По мере развития языка применимость его расширяется. На рис. 1.7 и 1.8 показаны два примера применения Java. Элементы управления ActiveX Ранее известные как OCX, элементы управления ActiveX стали ответной реакцией Microsoft на появление Java- аплетов. Они напоминают Java-аплеты, поскольку их можно использовать в качестве средств обеспечения выполняемого Web-содержимого (см. рис. 1.9). В отли- отличие от Java, область применения элементов у ipaej ActiveX ограничена только операционной средой Microsoft Windows. га-.- •¦.- Р SQIlUlWOStM lines 354 IS Ш ftnf* rip" ¦-;:¦ a „:::.._ as @ | -¦ *¦" bib ..,. ,j, i. E I * :РИСУНОК 1.7. Java-аплетперемещает самолет вдоль экрана. TjVMuJ H-fL Hrtreopt 3 &';& а) :м* Ш&: Virtual NYC РИСУНОК 1.8. Интерактивная карта, реализованная на Java. Несмотря на то что функционирование элементов управления ActiveX допускается только в одной опера- операционной системе, это не означает, что они недоступны для Web-приложений. Например, один и тот же элемент управления ActiveX можно использовать в Web-прило- Web-приложении и запускать его как в браузере с доступным ActiveX, так и в Delphi или Visual Basic. Высокое жюри все еще сомневается, что станет ап- летными стандартами — Java и ActiveX; что будет столь же известно, как и среда разработки Web-приложений? Но все же имеет место уклон в сторону ava (по боль- большей части, из-за опасений инфицирования вирусами,
JavaScript u Worldwide Web причиной которого могут стать элементы управления ActiveX). И в том, и в другом случае есть свои преиму- преимущества и недостатки. К счастью разработчиков JavaScript, программы могут взаимодействовать с обоими техноло- технологиями. Глава 25 посвящена совместной работе JavaScript и элементов управления ActiveX. РИСУНОК 1.9. 9то это — Javci-аплет или элемент управления ActiveX? РЕСУРС Информация по ActiveX может быть найдена в Internet- центре Microsoft no адресу http://www.microsoft.com/ com. . ¦ Подключаемые модули Netscape Подключаемые модули (plug-ins) — это несколько дру- другая технология, тем не менее представляющая собой клиентское расширение Web-браузера. Подключаемые модули существенно расширяют возможности браузера Netscape Navigator, связанные с поддержкой дополни- дополнительных типов данных. В частности, подключаемые мо- модули применяются для вывода на экран файлов различ- различных МШЕ-типов (multipurpose Internet mail extension, многоцелевые почтовые расширения). После запуска Netscape Navigator начинает поиск подключаемых модулей в папке program\plugins с целью их регистрации. Вызов подключаемых модулей выпол- выполняется по мере необходимости, когда обнаруживается файл MIME-типа. После инсталляции подключаемые модули стано- становятся добавочными модулями браузера и совершенно не нуждаются во взаимодействии с пользователем для сво- своего запуска. В действительности они необходимы для таких мультимедиа-данных, как звук, видео, графика. На рис. 1.10 показан подключаемый модуль, позволя- позволяющий просматривать файлы Adobe Acrobat в рамках Глава 1 Netscape. Для связи с модулями можно использовать JavaScript. Г М№ ¦ \b^.lli . »в a Pi ' ИХ Т. ч ¦ > и ¦ Adobe JQ&iii Коде и Macintosh Maw installing Acrobat ^еш-гг 4.0 tor Macintosh РИСУНОК 1.10. Просмотр файла PDFnpu помощи подключаемого модуля. Клиентские языки сценариев Последние штрихи магии клиентской части завершают клиентские языки сценариев. На сегодняшний день ос- основным таким языком является JavaScript, тем не менее компания Microsoft выдвигает собственную альтерна- альтернативу — VBScript. Наибольшей популярностью VBScript пользуется в кругу разработчиков на Visual Basic. В кон- конце главы можно найти краткое сравнение возможностей JavaScript и VBScript. Серверная часть Серверная часть среды разработки Web-приложений состоит из собственно Web-сервера плюс расширения серверного программного обеспечения. Как будет пока- показано несколько позже, эти расширения могут принимать различные формы и работать с различными технологи- технологиями. На рис. 1.11 показаны взаимосвязи внутри сервер- серверной части. Серверы Web-сервер загружается после отправки со стороны кли- клиента запроса на требуемые HTML-документы, после чего возвращает их для просмотра. Программное обес- обеспечение сервера — это приложение, выполняющееся на машине с установленным протоколом TCP/IP. Среди наиболее популярных серверов находятся Netscape Enterprise Server (NES), Microsoft Internet Information Server (IIS) и Apache. Серверные расширения Собственно Web-сервер обеспечивает передачу статичес- статических HTML-страниц клиенту при запросе, а также мно-
Знакомство с JavaScript Часть I жество других функций. С другой стороны, некоторые серверные расширения обеспечивают возможности, не реализованные в самом сервере. К таким возможностям относятся CGI, серверные API, JavaScript и Java. Клиенты Расширения РИСУНОК 1.11. Серверная часть. CGI Интерфейс общего шлюза (CGJ, Common Gateway Interface) представляет собой стандарт де-факто для организации взаимодействия внешних программ с Web- серверами. Запуская CGI-программы и сценарии на сервере, можно генерировать динамически создаваемое содержимое и отображать его пользователю. Типовой сценарий заключается в генерации запро- запроса из формы HTML и отправка его серверу. Запрос за- запускает CGI-программу или сценарий, размещенный в специальном каталоге на сервере. CGl-программа обра- обрабатывает запрос и возвращает HTML-документ с резуль- результатами. GI-программа может разрабатываться на любом языке программирования: Java, C++, Visual Basic, PHP, т.е. на том, что способно продуцировать код, могущий выполняться на Web-сервере. В мире Unix CGI-сцена- рии принято составлять на языках, подобных Perl или языкам командных оболочек Unix. Серверные API Другой способ интеграции с сервером предполагает ис- использование его собственного интерфейса прикладного программирования (API, Application Programming Interface). Два наиболее используемых API такого рода - Netscape Server API (NSAPI) и Misrosoft Internet Server API ASAPI). API обеспечивают более тесную ин- интеграцию с сервером. Например, в случае Windows для доступа со стороны сервера потребовалось бы создать библиотеку DLL, а не отдельный выполняемый модуль ЕХЕ. Использование серверных API обладает своим пре- преимуществом — потоки оказываются гораздо более эф- эффективными по сравнению с CGI-программами. CGI требует, чтобы для каждого клиентского запроса выпол- выполнялся отдельный экземпляр программы. Это приводит не только к большим издержкам, но также и к ограни- ограничению максимального объема совместно используемых данных. Недостаток использования серверного API шключа- ется в том, что полученное решение окажется специфи- специфическим для конкретного сервера. Созданная ISAPI DLL не будет работать с сервером Netscape. Разумеется, если работа связана постоянно лишь с одним сервером, упо- упомянутый негативный момент сводится на нет. Серверный JavaScript Повышенное внимание к JavaScript связано с возмож- возможностями, реализуемыми языком на стороне клиента. Однако, с не меньшим успехом JavaScript можно ис- использовать и в качестве серверного инструментального средства разработки сценариев. Как и следовало ожи- ожидать, первой средой подобного рода является Netscape. Среда Netscape SSJS (Server-Side JavaScript) позво- позволяет использовать сценарии для построения Web-при- Web-приложений, управляемых Netscape-сервером. Кроме того, существует несколько серверных расширений для язы- языка JavaScript, которые обеспечивают дополнительные возможности генерации динамического HTML, взаимо- взаимодействия с клиентом, доступа к внешним файлам на сервере и подключения к базам данных SQL (LiveWire). Следует отметить, что в ответ компании Netscape, Microsoft поддерживает JScript в качестве сернерно языка сценариев в рамках Active Server Pages. Java За последние месяцы Java существенно сдала свои по- позиции на серверной стороне. Компания Sun выпустила технологию под названием Java Server Pages (JSP), ко- которая призвана быть конкурентом ASP и SSJS. В насто- настоящее время компании Sun и Netscape объявили о со- создании своего рода союза, именуемого iPlanet, цель которого заключается, помимо прочего, в интеграции JSP и SSJS в единую технологически мощную среду. Вы, наверное, слышали о Java-сервлетах (Java Servlets). Сервлеты представляют собой небольшие компоненты, более всего похожие на элементы управления ActiveX в среде ASP, которые могут активизироваться как гото- готовые страницы либо использоваться для построения страниц. Это позволяет разработчикам направить на- накопленные знания Java (который намного проще в изу-
JavaScript u Worldwide Web Глава 1 чении, нежели С) на построение быстродействующих, надежных, не зависящих от платформы компонентов, предназначенных для создания страниц. Что можно сделать при помощи JavaScript? После краткого знакомства с технологиями разработки Web-приложений самое время посмотреть на роль кли- клиентской части JavaScript в Web-приложениях. Клиентские приложения JavaScript можно использовать для разработки полного клиентского приложения. Хотя JavaScript и не столь все- всеобъемлющий язык, каковым является Java, тем не менее, он проявляет существенные возможности при работе с дескрипторами HTML и связанными с ними объектами. Одно из наиболее известных приложений JavaScript, h Idaho Design's ColorCenter (http://www.hidaho.com/c3), показано на рис. 1.12. Данное приложение применяет- применяется для выбора цветов элементов, видимых в браузере, с возможностью их предварительного просмотра в отдель- отдельном фрейме. Создание аналогичного приложения с помо- помощью Java сопряжено с гораздо большими сложностями, связанными с необходимостью взаимодействия с HTML. Очевидно, что в отдельных случаях JavaScript обеспечивает практически идеальную основу для разра- разработки приложений. loisfrom Mfcbelow. Sd ftctive Link. Visited Link or Texture above to set the corresponding lors/textures. The current link colors arc shown on. the right. The cunent BODY tag is shown befow: hies sites by sele themfromthe drop-downlistabove and cEcbng Go, collect images by clicking the rightmou ton (Mac users click and hold) and ige Location* from the pep up menu. Then click on the text entry box пей to j|j v\t the image locabontheie (Ctri-vin Windows). Finally, click Add to add the Щ РИСУНОК 1.12. hIdaho Design's ColorCenter. Проверка допустимости данных JavaScript обеспечивает для Web-разработчиков возмож- возможность выполнять проверку допустимости данных, вво- вводимых пользователем, без необходимости обращения к серверу. Внутри кода JavaScript можно определить, яв- ляются ли значения, введенные пользователем, коррек- корректными, или, скажем, соответствуют ли они требуемому формату. Lopa3flo эффективнее провести проверку дан- данных в JavaScript, нежели передавать на сервер незавер- незавершенные данные. Подобного рода подход эффективен не только для пользователя, вводящего данных, но также и для сервера. При этом появляется уверенность, что пе- передаваемые на обработку серверу данные являются пол- полностью корректными. Создание интерактивных форм JavaScript также используется для "оживления" форм HTML. Одна из задач оживления связана с проверкой достоверности данных. Другая предполагает реализацию дополнительных возможностей, недоступных в HTML, как то поддержка информации в строке состояния, от- открытие второго окна браузера для отображения, скажем, справочной информации и т.п. Клиентские таблицы поиска Помимо проверки достоверности данных, один из спо- способов уменьшения потребности доступа к серверу зак- заключается в использовании JavaScript для генерации и поддержки клиентских таблиц поиска. Следует по- помнить, что в таком случае данные должны встраиваться в сам HTML-документ, поэтому использование таблиц поиска должно сводится к небольшим информацион- информационным базам данных, предназначенным только для чте- чтения. Поддержка состояния В Web-среде, не поддерживающей концепцию состоя- состояния, JavaScript применяется для поддержки состояния при обмене между сервером и клиентом. Основной спо- способ поддержки состояния связан с использованием на- наборов cookies (информации, сохраняемой браузером на стороне клиента). JavaScript обеспечивает как поиск, так и хранение cookie-наборов на клиентской части. Более детальная информация по работе с cookies может быть найдена в главе 30. Работа с Java-аплетами, элементами управления ActiveX и подключаемыми модулями По мере развития JavaScript, возрастают возможности работы с клиентскими расширениями, включая Java- аплеты, элементы управления ActiveX и подключаемые модули Netscape. Несложно получить доступ к свой- свойствам объектов Java и ActiveX, равно как и запускать их методы. Точно так же несложно определить, установ- установлен ли конкретный подключаемый модуль. Обладая подобной возможностью, JavaScript становится своего
Знакомство с JavaScript Часть I рода "клеем", соединяющим вместе HTML, аплеты и клиентские расширения. Поддержка JavaScript со стороны браузеров По сравнению с другими приложениями браузеры - относительно небольшие части программного обеспече- обеспечения, однако постепенно они превращаются в мощные приложения, воплощающие в себе все достижения Web- технологий. Браузер — это окно в Web, поэтому каким бы потенциалом на обладал бы JavaScript, однозначно плохо, если браузер не обеспечивает поддержку этого языка. Ниже будут рассматриваться особенности под- поддержки JavaScript в доступных на сегодняшний день браузерах.. Поскольку JavaScript — язык интерпретируемый и внедряемый в HTML-документы, он всецело зависит от работы программы! 'О обеспечения браузера. Устарев- Устаревшие браузеры не знают, что делать с таким кодом, и попросту проигнорируют его. Netscape Navigator К середине 90-х годов компания Netscape стала одной из самых влиятельных в Web-индустрии. Она не толь- только открыла для рынка различные технологические но- нововведения, но и объединилась с другими лидерами индустрии, такими как Sun, имея целью продвижение различных технологий в передние ряды Web. Поскольку разработчиком JavaScript является Netscape, вполне можно ожидать, что наилучшим в плане поддержки языка сценариев станет именно бра- браузер Navigator. Navigator 2.0 был первым браузером, поддерживающим JavaScript. Выпущенные позже версии привнесли важные усовершенствования в сам язык. По- Поскольку Navigator был перемещен в Mozilla.org, т.е. в зону Open Source (открытого исходного кода) Netscape, можно быть уверенным, что разработчики со всего мира в конечном итоге создадут практически идеальный бра- браузер. На рис. 1.13 показана бета-версия Mozilla (Netscape Navigator 5) с отображенной начальной страницей Mozilla.org. Microsoft Internet Explorer Microsoft Internet Explorer 3.0 — первый браузер, создан- созданный другой компанией, включающий в себя поддерж- поддержку JavaScript. Более ранние версии Internet Explorer не обладают поддержкой JScript, т.е. реализации JavaScript от компании Microsoft. Другие браузеры На момент написания книги существовало лишь три браузера, поддерживающих JavaScript: Sun's Hotlava 3.0 (JavaScript 1.4), Opera (JavaScript 1.1), Be's NetPositive 2.1 (экспериментальная версия). !Wkn ftb Qflui flA maznld.org 5 Released cdioaJ enough for . Tjsc buyalj.? to report nrt&Ciypta Announced ¦.1™*у-И№1 Uc i4« in РИСУНОК 1.13. Mozilla/Netscap(Navigator5. Сравнение JavaScript и JScript Как упоминалось ранее, JavaScript — не единственный язык сценариев, доступный в Web. На этой арене мо- могут выступать еще два участника: JavaScript/JScript и VBScript. Хоть данные языки и отдалились от действи- действительно конкурентно-способных языков (создается впе- впечатление, что на данный момент они просто дополня- дополняют друг друга), все же нелишним будет сравнить все достоинства и недостатки JavaScript и VBScript. Ниже рассматривается, что есть VBScript, как он соотносится с JavaScript, и для примера приводится простое VBScript- приложение. ПРИМЕЧАНИЕ Последние исследования показывают, что количество Web-сайтов, использующих VBScript, составляют незна- незначительную часть в общем числе сайтов, поддерживаю- поддерживающих JavaScript. Что такое VBScript? VBScript представляет собой язык сценариев для Web, разработанный компанией Microsoft, полностью парал- параллельный языку JavaScript. Все, что находится в основе VBScript, существенно отличается от первоистоков JavaScript. В то время как JavaScript создавался практи- практически "с нуля", слабо основываясь на C++ и Java, VBScript принадлежит к языковому семейству Visual Basic. Среди членов данного семейства: Visual Basic - распространенный язык программирования для Windows, Visual Basic for Applications — макроязык для Microsoft Office и других приложений. Если когда-либо доводилось разрабатывать программное обеспечение на
JavaScript u World Wide Web Visual Basic, гораздо быстрее получится освоить VBScript. Наиболее актуальная информация по VBScript находит- находится на сайте Microsoft по адресу http.'// www.msdn.microsoft.com / scripting. Встроенный язык HTML Как и JavaScript, VBScript является языком написания сценариев, внедренным в HTML-файлы. Подобно JavaScript, VBScript использует дескриптор <script> с указанием "text/vbscript" в качестве значения описате- описателя типа. Например, следующий сценарий отображает диалоговое окно предупреждения после загрузки стра- страницы: <html> <bead> <script type="text/vbscript"> alert("Is this JavaScript or VBScript?") </script> </head> </html> Самое интересное, что можно почерпнуть из приве- приведенного выше примера, так это то, что синтаксис двух языков совершенно одинаков. Если изменить параметр type на "text/javascript", результат останется тем же. Объектная модель Одним из наиболее важных факторов при сравнении JavaScript и VBScript является идентичная базовая объектная иерархия, хотя в других версиях могут суще- существовать и различия. Для Web-разработчика, использу- использующего оба языка, это — весьма приятный сюрприз, поскольку гораздо проще использовать синтаксически разные языки, нежели принципиально различные пара- парадигмы. Преобразование кода JavaScript в код VBScript или наоборот, как правило, носит построчный характер. В этих двух языках написания сценариев идентичны не только объектные модели, но также и способ работы с HTML-объектами. Подобно JavaScript, VBScript может реагировать на события, генерируемые HTML-объекта- HTML-объектами. Например, в следующем примере после нажатия кнопки Convert (листинг 1.2) все буквы текста, введен- введенного в поле myText, преобразуются в прописные. Листинг 1.2. Пример на JavaScript. <html> <head> <script type="text/javascript"> function convertText() { document.SampleForm.myText.value = document.SampleForm.myText.value.toUpperCase() Глава 1 </script> </head> <body> <form name="SainpleForm"> <input type="text" name="myText"> <input type="button" value="Convert" onclick="convertText()"> </form> </body> </html> Та же страница, но с использованием VBScript, выг- выглядит следующим образом: Листинг 1.3. Пример на VBScript. <html> <head> <script type="text/vbscript"> < ! — Sub convertText() document, SampleForm.myText. value = UCase (document .SampleForm.myText. value) End Sub </script> </head> <body> <form name="SampleForm"> <input type="text" name="myText"> <input type="button" value="Convert" onclick="convertText()"> </form> </body> </html> Более сложные типы данных На первый взгляд может показаться, что возможности работы с типами данных в VBScript существенно огра- ограничены. Но это лишь кажется, и причина состоит в том, что VBScript имеет только один тип данных — variant. При дальнейшем знакомстве с VBScript станет ясно, что поддержка типов данных здесь оказывается гораздо мощ- мощнее, нежели в JavaScript. Тип variant содержит инфор- информацию о значении, с которым он работает, поэтому в различных ситуациях имеется возможность запросить этот тип данных. Иными словами, если переменная типа variant используется как строка (см. следующий пример), VBScript рассматривает ее (myVar) как стро- строковое значение. myVar = "Stringl" + "String2" Совершенно аналогично, VBScript может рассматри- рассматривать ту же переменную как числовую: myVar =1 + 2 Строки и числа рассматриваются как подтипы внут- внутри типа variant. В таблицу 1.2 сведены подтипы VBScript.
Знакомство с JavaScript Часть I Таблица 1.2. Подтипы VBScript-типа variant. Подтип Описание String Строка переменной длины (максимальная длина — примерно 2 миллиарда символов). Byte Целое число между 0 и 225. Integer Целое число между-32168 и 32767 Long Целое число между -2147483648 и 2147483647. ¦Single Число с плавающей запятой одинарной точности со следующими пределами: от -3.402823Е38 до -1.401298Е-45для отрицательных и от 1.401298Е-45до3.402823Е38—для положительныхзначений. Double Число с плавающей запятой двойной точности со следующими пределами: от -1.79769313486232Е308 до -4.94065645841247Е-324для отрицательных и от 4.94065645841247Е-324до 1.79769313486232Е308—для положительных значений. Date (Time) Число, представляющее дату в пределах от 1/1/100 до 12/31/9999. Boolean Логическое значение (True или False). Empty Неинициализированная переменная. Значениями являются 0 для числовых и пустая строка ("")—для строковых переменных. Null Вариант содержит недопустимые данные (это не то же самое, что Empty). Object Объект ActiveX. Error Номер ошибки VBScript. VBScript обладает набором функций преобразования,, которые дополняют встроенные методы parsetFIoat и parselnt, определенные в JavaScript. Как и JavaScript, VBScript — слабо типизированный язык. Различные процедурные типы В VBScript определены два различных процедурных типа: подпрограммы и функции. Подпрограмма обозна- обозначается при помощи Sub..End Sub и представляет собой процедуру, не возвращающую значение. С другой сто- стороны, функция, обозначаемая парой Function..End Function — это процедура, которая возвращает значение. Например, следующая подпрограмма присваивает тек- текстовому объекту TextField строковый литерал "See Spot Run", но не возвращает значения в вызываемую проце- ДУРУ- <script type="text/vbscript"> Sub convertText () document.MyForm.TextField.value = "See Spot Run. " End Sub </script> Рассмотрим пример VBScript-функции. Подпрограм- Подпрограмма showText() вызывает функцию getText(), которая воз- возвращает значение текстового объекта TextField: <script type="text/vbscript"> Function get Text () getText = document.MyForm.TextField -value End Function Sub showText() alert (getText ()) EndSub </script> В JavaScript определен только один процедурный тип — метод (также называемый функцией), в котором ключевое слово function используется вне зависимости от того, возвращается или нет значение в вызываемую процедуру. Программирование в VBSript Для поверхностного ознакомления с программировани- программированием в VBScript воспользуемся простейшим примером. В листинге 1.4 выполняется умножение двух значений, введенных пользователем, и отображение результата в диалоговом окне предупреждения: Листинг 1.4. Пример программы на VBScript. <html> <head> <title>Wizard</title> <script type="text/vbscript"> Sub calculateValuesO Dim numl, num2, greaterNum, totalVal numl = document. forml.Number1.value num2 = document. f onnl. Number2 . value totalVal = numl*num2 alert (totalVal) End Sub </script> </head> <body> <hl>Stump the Wizard</hl> Without connecting to a backend server or
JavaScript u World Wide Web using a Java applet, the Browser Wizard will multiply the two numbers . . . <?orm name="forml" method="POST"> <pre> First Number: <input type="text" size=" maxlength="S" name="Numberl"> </pre> <pre> Second Number: <input type="text" size=" maxlength=" name="Number2 " > </pre> <P> <input type=button name="WizButton" value="Multiply" ondick="calculateValues () </form> </body> </htrol> На рис. 1.14 показаны результаты выполнения это- этого сценария в Internet Explorer 5.0. Для целей сравнения двух языков в листинге 1.5 приводится эквивалентный код на JavaScript. Stump the Wizard Without «omectmg tts> aibackemf шнег ty using a Java applet, the Browser "Wizard wulmubpfythe twonumbeis. Hist Murtier: JI2 щГтТпТЩТЯТШаП РИСУНОК 1.14. Результирующее окно сообщений. Листинг 1.5. JavaScript-версия кода, приведенного в листинге 1.4. <html> <head> <title>Wizard</txtle> <script type="text/javascript"> <t — function calculateValues() { Глава 1 numl = parseFloat (document.forms[0] .Numberl .value) num2 = parseFloat (document. forms [ 0 ] . Number2 . value) result = iiiiiiiI * num2 alert (result); } II—> </script> </head> <body> <hl>Stump the Wizard</hl> <P> Without connecting to a backend server or using a Java applet, the Browser Wizard will multiply the two numbers . . <form name="?orml" method="POST"> <pre> First Number: <input type="text" size=" maxlength=" name="Numberl"> </pre> <pre> Second Number: <input type="text" size=" maxlength=" name="Number2"> </pre> <P> <input type="button" name="WizButton" value="Multiply"ondick="calculateValues () " </?orm> </body> </html> Резюме Глава посвящена исследованиям среды разработки Web- приложений и существующей методики объединения отдельных частей Web-технологий. JavaScript — одно из важнейших инструментальных средств в наборе Web- разработчика. Было показано, что JavaScript взваливает на себя множество реальных функций, возникающих в течение цикла создания Web-приложений. JavaScript неуклонно становится стандартным языком Web-разра- Web-разработки. Поскольку JavaScript — язык, а не инструмент, он зависит от программного обеспечения браузера. С момента захвата браузерами Microsoft Internet Explorer и Netscape Navigator крепких позиций на рынке, надеж- надежность поддержки JavaScript существенно увеличилась. Сейчас вы обладаете вполне достаточными знания- знаниями, чтобы успешно освоить материал следующей гла- главы, которая посвящена взаимодействию JavaScript и HTML.
Совместная работа JavaScript и HTML В ЭТОЙ ГЛАВЕ Основы HTML Внедрение JavaScript в HTML Создание JavaScript-кодов HTML дает возможность создавать замечательные статические Web-страницы. Хоть эти документы зачас- зачастую и оказываются высокохудожественными, интерес- интересными и во многом полезными, JavaScript позволяет пре- превратить статические Web-страницы в интерактивные и сделать их более чувствительными к пользовательским действиям и вводу. Расширение HTML-страниц с помо- помощью JavaScript усиливает их возможности, а также су- существенно увеличивает гибкость кода. JavaScript позволяет разработчику Web-сайта созда- создавать более динамические Web-страницы за счет вклю- включения в существующую структуру HTML JavaScript- сценариев. В этом случае разработчик может назначать кнопкам некоторые процессы, выполнять вычисления для введенных в форму данных либо обеспечивать определенные действия при попадании курсора мыши на элемент HTML или объект Document. В общем,, HTML становится значительно интереснее. JavaScript обладает рядом преимуществ перед фор- формируемыми на сервере интерактивными документами при помощи CGI,, поскольку написанные на JavaScript документы, вообще говоря, не зависят от обработки на сервере, а следовательно, быстрее реагируют на запро- запросы пользователя и быстрее взаимодействуют с ним. Для более глубокого понимания работы JavaScript в мире HTML стоит сделать обзор основ HTML, пресле- преследуя цель посмотреть, какое он имеет отношение к это- этому языку сценариев. Обладая устойчивой базой знаний по HTML, разработчик сможет более полно овладеть JavaScript и другими интерактивными возможностями, а так же высокоуровневыми функциональными возмож- возможностями HTML. Основы HTML Несмотря на очевидную простоту разработки простых HTML-документов, включающих основные теги и про- простые формы, преимущество применения HTML состо- состоит в возможности создания сложных документов на ос- основе более простых. Если задействовать более сложные дескрипторы и связанные с ними атрибуты, сложность и степень применимости документов будет возрастать, а частота использования метода проб и ошибок - уменьшаться. Текущая ситуация Стандарты HTML изменяются постоянно. Текущие ре- рекомендации (то бишь, стандарт) охватывают HTML 4.01; однако, следующее поколение HTML — это XHTML. В настоящее время XHTML 1.0 — предложенный вариант стандарта, ожидающий принятия консорциумом Word Wide Web Consortium (W3C) и основанный на рекомен- рекомендациях для HTML 4.01. XHTML — это HTML, существующий в виде при- приложения XML. После принятия XHTML в качестве стандарта, прикладные XML-программы получат воз- возможность обрабатывать данные в XHTML-документах. Использование XML продемонстрирует, что XHTML также позволяет включать в документы и другие диалек- диалекты (типа MathML). В любом случае, развитие этих тех- технологий породит новые элементы, равно как и усовер- усовершенствованные новые атрибуты элементов. Ресурс -,-..- ;^~, „.,; - ¦¦"¦ .->, -, ""т ;1 Рассмотрение XHTML выходит за рамки этой книги. Подробную информацию о нем можно получить на Web-сайте W3C по адресу http://www.w3.org.
Совместная работа JavaScript и HTML Отслеживая самые последние выпуски популярных браузеров, HTML-разработчик будет равняться на эти усовершенствования и применять их, как только они станут доступны широкой публике. К счастью, практи- практически всегда расширения, включаемые в HTML 4.01/ XHTML 1.0 и последние выпуски браузеров, при про- просмотре в более старых браузерах проблем не создают. Однако всегда следует тестировать документ в старых бра- браузерах, поскольку гарантия правильного восприятия но- новых дескрипторов в таких браузерах лишней не окажется. Следует отметить, что существуют дескрипторы, которые не являются частью стандарта или работают не во всех браузерах. Пример такого дескриптора - <marquee>; он работает в Internet Explorer, но не в Navigator. Последний будет отображать просто текст документа. С другой стороны, Navigator поддерживает, например, дескрипторы <1ауег> и <ilayer>, невоспри- нимаемые Internet Explorer. Приведенные примеры иллюстрируют важность на- написания четко определенного и сегментированного до- документа и обязательного учета различий браузеров при создании Web-страниц. Основы HTML Поскольку клиентский JavaScript работает бок о бок с HTML, прежде чем приступать к созданию каких-либо сценариев, необходимо получить основные знания о структуре НТМ L-документа и его дескрипторах. Знание основ HTML существенно упростит создание Web-стра- Web-страниц. Web-страница состоит из текста страницы, деск- дескрипторов, и может иногда содержать комментариев. Текст — это понятно и без пояснений. Разработчик пишет текст, который появляется на Web-странице. Часть процесса дизайна Web-страниц, которая требует более подробных пояснений, — это использование деск- дескрипторов, всегда начинающихся с символа < и заверша- завершающихся символом >. Дескрипторы определяют поведение Web-страницы, задают внешний вид текста и позволяют создавать сложные документы для Web-браузера. Дескриптором может быть одиночный маркер, на- например, <hr> — для горизонтальной линии, или <br> — для перевода строки; подобного рода дескрипторы иног- иногда называют пустыми. Пустые дескрипторы не обяза- обязательно каким-то образом форматируют окружающий текст, хотя и способны корректировать разметку и ди- дизайн НТМ L-документа. С другой стороны, <td> нельзя рассматривать как пустой дескриптор. Он используется для указания на то, что текст, следующий после этого дескриптора, должен помещаться в ячейку таблицы. Дескрипторы такого типа требуют наличия закрывающего дескриптора, уве- уведомляющего о завершении их действия. Эти дескрипто- дескрипторы называются контейнерными, поскольку всегда содержат информацию (обычно текст) между открывающим и зак- Глава 2 рывающим дескрипторами. Исследуя приведенный ниже пример, обратите внимание, что закрывающий дескрип- дескриптор перед именем содержит символ /: <Ъ>Этот текст становится полужирным</Ь> Закрывающий дескриптор идентичен открывающему, за исключением того, что он содержит дополнительный символ. Более сложные дескрипторы могут также иметь ат- атрибуты, которые определяют поведение дескриптора. Если дескриптор располагает подобного рода атрибу- атрибутам, они необходимы дескриптору для исполнения оп- определенных требований. Например, <table width="> определяет таблицу с шириной 3. Расположение дескрипторов в документах иногда имеет очень важное значение. Некоторые дескрипторы необходимо помещать внутрь других. Например, деск- дескриптор <input> должен находиться внутри <form>. Не- Некоторые дескрипторы могут включать в себя другие, но это не является обязательным условием (примером мо- может послужить дескриптор <head>). Что касаемо комментариев, они суть ни что иное как примечания разработчика по поводу собственно- собственного документа, которые браузером не отображаются. HTML-комментарии начинаются с символа <!— и за- заканчиваются на —>. Ниже приводится пример HTML- комментария: - вот вам и комментарий —> Структура HTML-документа Структура HTML-документа зачастую очень важна. При неправильном размещении дескрипторов увеличивает- увеличивается вероятность возникновения нежелательных и неожи- неожиданных эффектов. Базовый HTML-документ показан на рис. 2.1. Документ всегда должен начинаться с <html> и завершаться </html>, что несложно заметить в лис- листинге 2.1. Два основных дескриптора внутри упомяну- упомянутых — <head> и <body>. Внутри них можно размещать остальные дескрипторы. X ... a ж РИСУНОК 21. Базовый HTML- документ, показанный в листинге 2.1. Heading of Basic Document 1, Ooe 2. Two "Ibis is a basic HTML -iorumetit jbucnirc :-^я?!Ш^ЕШяЩИгШ38ЁЕ^&м&
Знакомство с JavaScript Часть I Листинг 2.1. Базовая HTML-страница. <html> <head> <title>Basic HTML document</title> <script type="text/javascript"X/script> </head> <body> <hl>Heading of Basic Document</hl> <form> <input name="EnterBtn" type="SUBMIT"> </form> <ol type=l> <table width=" height=" border> <tr> <th colspan=">Table</th> </tr> <tr> <td>celll</td> <td>cell2</td> <td>cell3</td> </tr> <tr> <td>cell4</td> <td>cell5</td> <td>cell6</td> </tr> </table> This is a Basic HT№ document structure . </body> </html> Основное об атрибутах Как упоминалось ранее, многие дескрипторы имеют атрибуты. Атрибуты используются для определения отображения или исполнения дескриптора. Атрибута- Атрибутами обладают далеко не все дескрипторы, а некоторые из них могут иметь атрибуты с одинаковыми именами. Атрибуты, перечисленные в табл. 2.1, используются во множестве НТМ L-дескрипторов. Функциональность этих атрибутов от дескриптора, их использующего, не зависит. Внедрение JavaScript в HTML JavaScript-сценарии интегрируются в HTML-докумен- HTML-документы с использованием пары дескрипторов <script> и </script>. HTML-документ может содержать множество подобных пар, причем каждая из них зачастую заклю- заключает в себе более одного набора операторов JavaScript. Для <script> обязательно требуется присутствие </script>. Атрибут type используется для определения языка, на котором реализован сценарий, а атрибут src — для за- задания имени внешнего файла, являющегося источником JavaScript-программы. Атрибуты дескриптора <script> Для лучшего понимания принципов функционирования дескрипторов <script> выполним краткую сводку раз- различных атрибутов в табл. 2.2. В разделах, приведенных после этой таблицы, можно отыскать более детальную информацию, касаемую каждого из перечисленных ат- атрибутов. Таблица 2/1 .^Атрибуты, используемые в различных дескрипторах. Атрибут Описание class Определяет класс, к которому принадлежит HTML-дескриптор. id Определяет некоторое уникальное значение для элемента при ссылке на полный документ. name Присваивает имена экземпляру дескриптора. Это имя часто используется JavaScript для ссылок на конкретные элементы либо дескрипторами <а> для организации ссылок в пределах одного документа. style Определяет информацию о стиле. Таблица 2.2. Атрибуты дескриптора <script>. Атрибут Описание defer Это атрибут логического типа, который используется для уведомления браузера о том, генерирует ли JavaScript-сценарий какое-либо содержимое. language Отвергнутый в настоящее время, однако применяемый ранее атрибут для определения языка и версии, используемых внутри дескрипторов. src Этот атрибут определяет URL внешнего исходного JavaScript-файла. type Атрибут, пришедший на замену language; он сообщает браузеру, какой язык используется внутри дескрипторов.
Совместная работа JavaScript и HTML defer Атрибут defer — это простой атрибут, который сообща- сообщает браузеру, будет ли код, расположенный между от- открывающим и закрывающим дескрипторами <script>,, генерировать какое-либо содержимое. Другими словами, используется ли в коде метод document.write(). Ниже приводится пример использования данного атрибута: <script type="text/javascript" defer> // Просто объявим переменную; пока не стоит // ее выводить на страницу ¦var myVar = 500; //--> </script> language В самой последней версии языков HTML и XHTML атрибут language отвергнут. Традиционно он использо- использовался для определения имени языка и версии JavaScript, которые использовались для кода, расположенного между парой <script>. Формат этого дескриптора выг- выглядит так: <script language="JavaScript"> Таблица 2.3. Текущие значения атрибута language. Глава 2 Приведенная выше запись уведомляет браузер, что сценарий необходимо выполнять в режиме, совмести- совместимом с JavaScript 1.0. Для других версий JavaScript, на- например, 1.1, следует записать так: <script language="JavaScriptl.1"> В табл. 2.3 перечисляются значения, которые можно использовать с атрибутом language. Она также показы- показывает, какие браузеры будут интерпретировать то или иное значение. ;;;совет ¦ •/ ' : Если атрибут language не определен, браузеры при- принимают JavaScriptl .0. Кроме того, текущая версия браузера Opera, кажется, вообще игнорирует этот ат- атрибут, поскольку он был в свое время отвергнут. Используя атрибут language, можно определить множество наборов функций JavaScript. Браузеры, под- поддерживающие JavaScript 1.1, смогут воспользоваться пре- преимуществами более новых функций, которые недоступ- недоступны в старых версиях браузеров. Простейший метод задействования преимуществ подобного рода показан в листинге 2.2. Значение language Описание JavaScript Представляет JavaScript 1.0 и интерпретируется браузерами Navigator 2+ и Internet Explorer 3+. JavaScripti. 1 Представляет JavaScript 1.1 и интерпретируется браузерами Navigator 3+ и Internet Explorer 3+. JavaScriptl .2 Представляет JavaScript 1.2 и интерпретируется браузерами Navigator 4+ и Internet Explorer 4+. По сравнению с 1.1, в JavaScript 1.2изменен способ, в соответствие с которым Navigator обрабатывает некоторые операторы. JavaScriptl .3 Представляет JavaScript 1.3и интерпретируется браузерами Navigator 4.05+ и Internet Explorer 5+. JavaScriptl.4 Представляет JavaScript 1.4 и интерпретируется HotJava 3+ и некоторыми ранними альфа-версиями (до версии М12) Mozilla/Navigator5. JavaScriptl.5 Представляет JavaScript 1.5 и интерпретируется браузером Mozilla/Navigatorbeta 1.0(M12+). Листинг 2.2. Одновременное использование разных версий JavaScript в атрибуте language. <html> <head> <ti 1:1е>Определение версий JavaSoript</title> </head> <body> <script language="JavaScript"> / / Этот раздел будут читать только браузеры с JavaScript 1.0 document.write ('Браузер поддерживает JavaScript 1.0<br>'); </script> <script language="JavaScriptl.1"> // Этот раздел будут читать только браузеры с JavaScript 1.1 document.write('Браузер поддерживает JavaScript l.l<br>'); </script> <script language="JavaScriptl.2"> // Этот раздел будут читать только браузеры с JavaScript 1.2 docjment.write( 'Браузер поддерживает JavaScript 1.2<br>'); </script>
Знакомство с JavaScript Часть I ocript languages" JavaScriptl. 3"> // Этот раздел будут читать только браузеры с JavaScript 1.3 document.write('Браузер поддерживает JavaScript 1.3<br>'); </script> ¦<script language^"JavaScriptl.4"> // Этот раздел будут читать только браузеры с JavaScript 1.4 document.write('Браузер поддерживает JavaScript 1.4<br>'); </script> <script language»" JavaScriptl. 5"> // Этот раздел будут читать только браузеры с JavaScript 1.5 document.write (¦ Браузер поддерживает JavaScript 1. 5<br>') ,• </script> </body> </html> src Существуют два пути интегрирования операторов JavaScript в HTML-документ. Выбор пути зависит от требований при просмотре и изменении кода. Первый вариант позволяет рассматривать все коды одновремен- одновременно и предполагает написание операторов JavaScript не- непосредственно в HTML-документе, Все эти операторы встраиваются в HTML-страницу между парой дескрип- дескрипторов <script>; они носят название встроенных (inline) сценариев. Второй вариант (доступный только в JavaScript 1.1 и старше) предполагает сохранение JavaScript-кода в отдельном файле с расширением js. В таком случае по- появляется возможность обращения к файлу в открываю- открывающем дескрипторе <script>. Ниже показан первый вариант—встраивание JavaScript в HTML-страницу: ocript type="text/javascript"> function options 0 { document.write("Встраивание кода"); > </script> А сейчас — вариант с размещением сценария во внешнем файле: <script src="/jscripts/myscript.js"X/script> Во втором варианте потребуется создать файл с име- именем myscript.js, который будет содержать одну строку кода: document .write ("Вызов из отдельного файла") В случае использования последнего варианта между парой дескрипторов <script> желательно поместить один оператор, тем самым обеспечивая пользователям воз- возможность обратной связи на случай, если файл с расши- расширением .jsоказывается некорректным или недоступным. Иначе пользователь будет лицезреть неправильное по- поведение Web-страницы, не понимая его причин. При загрузке сценария из отдельного файла необхо- необходимость в указании атрибута language не возникает до тех пор, пока применяется файл с расширением .js. Пользуясь этим методом, можно изменять JavaScript-код без какого-либо открытия и риска возникновения неже- нежелательных изменений в HTML-страницах. Следователь- Следовательно, код подобного рода представляется более модуль- модульным и переместимым, поскольку он размещается за пределами HTML-документа. Отрицательная сторона метода состоит в том, что приходится модифицировать два набора кода, в зависи- зависимости от изменений в коде JavaScript. Например, если в JavaScript-коде изменяется имя функции, следует не забыть изменить соответствующее имя в обращениях к этой функции и в HTML-коде. Еще один минус связан с тем, что внешние JavaScript-файлы не могут содержать дескрипторы HTML; они должны содержать только операторы JavaScript. type Те, кто уже работал с JavaScript ранее, возможно, гово- говорили: "Что это за птица такая, атрибут type? Я думаю, здесь следует использовать language." Да, в какой-то сте- степени это правильно. Атрибут language был первым атрибутом, который не только определял язык в дескрипторе <script> напри- например, javascript или vbscript, но также и версию, скажем, javascriptl.l или javascriptl.5. Если просмотреть текущий стандарт HTML или предложенные рекомендации по XHTML, несложно заметить, что от атрибута language было решено отказаться, а вместо него использовать type. Значение, указываемое в этом новом атрибуте очень смахивает на указание в качестве содержимого внешне- внешнего исходного файла на JavaScript (js). Так, для JavaScript необходимо задать type="text/javascript", адля VBScript — type="text/vbscript". Далее показано, как это работает. Рекомендации HTML 4.01 говорят, что в часть <head> документа следует помещать дескриптор <meta>, кото- который будет определять заданный по умолчанию язык, используемый во всех сденариях. Это выглядит так: <meta http-equiv="Content-Script-Type" content="text/j avascript">
Совместная работа JavaScript и HTML Глава 2 Здесь можно заменить text/javascript на text/vbscript или любой другой язык, который планируется исполь- использовать. Если подобную строчку не указывать вообще, браузеру потребуется проверить элемент Content-Script- Type в заголовке HTTP-запроса. Формат выглядит сле- следующим образом: Content-Script-Type: text/javascript Опять-таки, text/javascript можно заменить на кон- конкретный тип языка, заданный по умолчанию для дан- данной Web-страницы. Теперь, когда тип языка по умолчанию установлен, атрибут type будет применяться для отмены значения по умолчанию. Это позволяет использовать сразу не- несколько языков сценариев в одном и том же документе. Например, можно установить Content-Script-Type рав- равным text/javascript, а затем указать type="text/vbscript" в одном из дескрипторов <script>, в пределах которого в качестве языка будет использоваться VBScript. Очевидно, что этот атрибут будут учитывать только новые браузеры, поэтому применять его следует с осо- особой осторожностью. Возможно, через пару лет все вста- встанет на свои места и большинство браузеров будут под- поддерживать этот новый метод. Однако сейчас рекомендуется использовать в дескрипторе <script> как type, так и language. Просмотр кода JavaScript Поскольку код на JavaScript можно записывать непос- непосредственно в коде HTML, просматривать и редактиро- редактировать его легко. Вероятно, вам уже знаком пункт меню браузера Document Source (или Page Source), который обеспечивает просмотр исходного текста HTML-страни- HTML-страницы (он обычно находится в меню View). При просмотре исходного кода документа можно также исследовать JavaScript-код, включенный в доку- документ, как показано на рис. 2.2. (Здесь, очевидно, как раз тот случай, когда операторы JavaScript вызываются из файла .js вместо помещения их непосредственно в до- документ. Все что можно здесь наблюдать — это обраще- обращение к файлу .js в дескрипторе <script>.) Для JavaScript не требуется специальное средство просмотра, и по- поскольку характер языка — интерпретирующий, а не ком- компилирующий, код отображается в исходном тексте до- документа. ПРИМЕЧАНИЕ Некоторые браузеры, в особенности Navigator 4, при выборе пункта меню View Source отображают лишь результаты выполнения кода на JavaScript. В этих слу- случаях для просмотра и пошагового выполнения сцена- сценариев рекомендуется воспользоваться отладчиком Netscape JavaScript Debugger, который обсуждается в глаз. 34. <script'langua Cl Start: ТооЩлг for dam-level browsers—>\ <SPftH ID-"TBDawnl.euelDiu"> <TfiBU MIDTH-'IOOV CELLPflPDINC-Q CELLSPflCIMC-0 BDRDEB-0 DGCOLOfi-'UFFFFFF'> <TR> <TD UftUCH-TOP1 HEICMT-6O П01ЛРЛН-2ХЙ HREF-"/isapt/goi»scon.asp?target-/' TARGET-' top'XIHG SRC-'/librai-y/hOMPpage/inaqes/bnr all.gif ¦ UIDTH-25O HEIGHTS» rtLT-'Bici-uiofl.cgn Ионе' DORD?R-Q></AX/TD> <TD VftLJCH-TOP' HEICHT-20 flLlGH-'RICHl-XIHG SRC-'/library/tODlbar/inages/curue.gif VIDTH-1B KEIGHT<-2B flLT-" B0RDERX/TD> <TD DGCOLOR-'ttOOOOOD' HEIGHT-ZO UflLICM-'MIDDLE" flLlPH-'RIGHT * NQWRflP C0LSPflH-2> <FOHT COt_OR-4FFFFFF- FftCE-' Uerdana, Arial' SJZE-1> &nbsp;ftnbsp;<A STVLE-*colortBFFFFFFjteKt-decofationinotie;1 IRCr-'/i5api/gonscon.asp?tat-get«/cataIog/(IefauIt.asp7bUtiid-22' TflRCET-" top'XFDHT COLOR-' BFFFFFF *>Ali Prodtict3</F0HTX/ft>&nbsp;f.nbsp;<F0HI C0L0R-4tFFFFFF*>|</FOHT> snDsp:cnDsp;<A STVLE-"color:BFfFFFF;te«t-decoration:none;* HRtf-Vlsapi/gonscon.asp?target-/suppot't/' TARGET-1 top'XFOHT COLOR ' «FFFFFF ' >SupporC</FOHT></A>Anbsp;&nbsp;<FONTCOLOR- ' BFFFFFF ">| </FOHT> ЕлЬ5р;Г(ПЬ5р;<П РИСУНОК 2.2. Просмотр JavaScript-кода. Создание JavaScript-кода ¦Основы создания JavaScript-кода весьма просты. Доста- Достаточно только создать основную HTML-страницу (или отредактировать существующую) и затем вставить дес- дескрипторы <script> в разделы <head> или <body>. Фун- Функции и другие элементы, которые применяются ко всей Web-странице, лучшие помещать в раздел <head>. При наличии необходимости генерировать текст для Web- страницы при помощи JavaScript, это лучше выполнять в разделе <body>. Выполнение сценариев Выполнение JavaScript-сценариев начинается в разное время, в зависимости оттого, как они написаны. Если сценарий влияет на содержимое Web-страницы, напри- например, вызывает метод document.write(), он выполяется по мере своего появления. Кроме того, существует обработ- обработчик событий onLoad, который выполняется только пос- после полной загрузки HTML-документа в браузер. Если JavaScript-сценарии сохранены в отдельном файле, они анализируются во время загрузки Web-стра- Web-страницы и перед любыми действиями пользователя. Все операторы JavaScript, содержащиеся в теле фун- функции, интерпретируются, однако запуск функции не происходит до тех пор, пока она не будет вызвана ка- каким-то JavaScript-событием. Операторы JavaScript, на- находящиеся за пределами тела функции, выполняются после загрузки документа в браузер, но во время визуа- визуализации документа. Результат выполнения станет оче- очевиден для пользователей уже при первом просмотре Web-страницы. Загрузка Web-страницы Операторы JavaScript, которые требуют немедленной обработки, выполнятся сразу после загрузки Web-стра- Web-страницы, но до ее отображения в браузере. Код в листинге
Знакомство с JavaScript Часть I 2.3 обеспечивает отображение диалогового окна предуп- предупреждения после открытия документа. Вызова функций не происходит — операторы JavaScript просто обраба- обрабатываются по мере загрузки Web-страницы. Листинг 2.3. Отображение диалогового окна предупреждения за счет непосредственного вызова. <html> <head> <title>Dialog Test</title> <script type="text/javascript"> < ! — alert. <"Dialog called") ; // —> </script> </head> <body> <b> Test page of defauJ JavaScript call </fcody> </html> Функция onLoad может рассматриваться как исклю- исключение из этого правила. В данном случае onLoad вызы- вызывается не в результате генерации события пользовате- пользователем, а в результате события, связанного с собственно загрузкой документа в браузер. Диалоговое окно пре- предупреждения будет появляться непосредственно после зафузки Web-страницы (см. рис. 2.3), и это при том, что окно не вызывается напрямую. В листинге 2.4 показа- показана функция opendoc(), вызываемую самим документом после генерации его события Load. Оба листинга B.3 и 2.4) обеспечивают одни и те же результаты, достига- достигаемые, однако, двумя разными способами написания сценария. Листинг 2.4. Отображение диалогового окна предупреждения через <html> <head> <title>Dialog from onLoad</title> <script type="text/javas <! — functionopendoc() { alert ("Dialog called ") ) / / ^ </script> </head> <body onload="opendoc () "> Test page of onLoad JavaScript call </body> </html> Пользовательские действия Второй метод, в соответствие с которым выполняются операторы JavaScript, — это вызов функций. Любой опе- оператор, содержащийся в функции, не будет выполняться до тех пор, пока JavaScript-событие не вызс эту фун- функцию. JavaScript-события генерируются на HTML-стра- HTML-странице многими способами, включая действия пользова- пользователя и явные вызовы событий непосредственно изнутри сценария. Пользовательские действия в документе спо- способны генерировать JavaScript-события в многих случа- случаях, даже в самых неожиданных. Всегда следует тщатель- тщательно протестировать все операторы JavaScript, дабы убедиться, что пользовательское взаимодействие с Web- страницей не вызывает нежелательные события. РИСУНОК 2.3. Диалоговое окно предупреждения в Navigator 4.7. В главе 14 JavaScript-события, их реализация и встра- встраивание в HTML-код рассматриваются более подробно. В листинге 2.5 приведен код, который обеспечивает отображение диалога в результате нажатия кнопки. Листинг 2.5. Вызов функции для отображения диалога. _ <html> <head> <title>Dialog from function call</title> <script type="text/javascript"> function opendoo () { ("Dialog called by Push Butto </script> </head> <body> <b> Test page of function called from Push Button <form method="POST"> <input type="Button" name="BUTTONl' value="PUSH" onclick="opendoc () "> </form>
Совместная работа JavaScript и HTML Глава 2 </body> </html> На рис. 2.4 показаны результаты вызова функции. Teitpage of font do ¦ © i caUed from Push Butto 0 is* аи Ed ii ii РИСУНОК 2.4. Диалоговое окно предупреждения в Internet Explorer5, вызванное событием submit. Пользовательские действия или явные вызовы собы- событий — это часто используемые методы выполнения JavaScrpt-кода. Исключительное преимущество JavaScript заключается в том, что он способен увеличивать коли- количество взаимодействий пользователя с HTML-докумен- HTML-документом, поскольку обеспечивает способ немедленной обра- обработки и оценки вводимой пользователем информации. Учет браузеров, не поддерживающих JavaScript Быстрые темпы изменений HTM L и JavaScript требуют предельно осторожного отношения к браузерам, которые не поддерживают создаваемые документы. Не все брау- браузеры поспевают за новыми изменениями в HTML, по- поэтому программисты вынуждены делать документы мак- максимально дружественными по отношению ко всем 'браузерам и средам. СОВЕТ Тестируйте свои HTML- и JavaScript-страницы в как можно большем количестве браузеров; такая поли- политика приведет к максимальной стабильности и приме- применимости документов. Хотя применение JavaScript делает усовершенствова- усовершенствования HTMLflocTynHbiMH для пользователей, необходимо всегда помнить, что старые браузеры не способны под- поддерживать JavaScript-код. Если окружить дескриптора- дескрипторами комментария HTML все операторы внутри пары <script> и </script>, более старые браузеры смогут ото- отобразить Web-страницу, не показывая JavaScript-код. Пользователи не смогут получить полное впечатление от Web-страницы, но, по крайней мере, в браузере не по- появится нежелательный текст. Формат использования этих комментариев таков: <script type="text/javascript"> <!— скрыть код от старых браузеров // здесь начинается собственно код // а здесь код завершается —> </script> Листинг 2.6 демонстрирует способ сокрытия кода JavaScript от старых браузеров. Обратите внимание, что в этом листинге применяются два следующих друг за другом оператора HTML-комментариев, а строки кода на JavaScript размещаются внутри них. Листинг 2.6. Сокрытие JavaScript-сценариев от старых браузеров. <html> <head> <title>Hide From Browser</title> <script type="text/javascript"> - Скрыть document.write("I can view JavaScript code") // Завершить сокрытие —> </head> <body> Content goes here. </body> </html> Обратите внимание, что в последней строке коммен- комментария HTML используется дескриптор JavaScript-ком- JavaScript-комментария //, поэтому JavaScript не интерпретирует этот оператор. В случае отсутствия этих маркеров коммен- комментария JavaScript будет пытаться обрабатывать оператор и после оценки сгенерирует ошибку. В листинге 2.7 показан текст базовой Web-страни- Web-страницы, с которой стоит начать. Обратите внимание на нор- нормальные HTML-дескрипторы и на <script>, присут- присутствующий в разделе <head> документа. Листинг 2.7. Базовый JavaScript-документ для начинающих. <html> <head> <title>My first HTML page</title> <script type="text/javascript"> <f — Скрыть //Здесь должен находиться код // Завершить сокрытие—> </script> </head> <body> - Здесь находится содержимое страницы —> </body> </html>
Знакомство с JavaScript Часть I Открывающий дескриптор <script> должен включать в себя атрибут type для определения того, что сценарий внутри дескрипторов реализован именно на JavaScript. Помните, что до тех пор, пока рекомендации HTML 4.01/XHTML 1.0 не будут В полном объеме реализова- реализованы в наиболее распространенных браузерах, можно так- также использовать и атрибут language. Написание кода Как и в любом другом языке программирования, опе- операторы JavaScript могут быть записываться в соответ- соответствие с различными методами. Очевидно, практика оп- определения функций JavaScript в разделе <head> и последующий вызов этих функций в разделе <body> — самый эффективный способ использования преиму- преимуществ объектов JavaScript. Сам по себе язык JavaScript не труден, и разработ- разработчики, владеющие технологией объектно-ориентирован- объектно-ориентированного программирования, не встретят слишком много препятствий. Как только будут схвачены основные кон- концепции объектной методологии, создание функций JavaScript становится достаточно простым делом. По- Посмотрите на следующий пример: document.write("Я мору видеть код на *¦• JavaScript!"); ¦Оператор document.write() как-будто бы говорит: "За- "Записать такой-то текст в моем документе". "примечание ./;¦;, « ^*; ' Несмотря на то что операторы HTML не чувствитель- чувствительны к регистру (хотя в предложенных рекомендациях XHTML подобное требование присутствует), операто- операторы JavaScript — чувствительны. Не забывайте прове- проверять регистр символов кода, чтобы гарантированно не иметь проблем из-за столь досадного, но все же рас- распространенного недоразумения. Приступая к написанию кода, памятуйте о следую- следующем: Повторное использование кода Удобочитаемость Простота внесения изменений Дескрипторы JavaScript можно использовать как в разделе <body>, так и в разделе <head> документа. Как упоминалось ранее, помещение дескриптора <script> в <head>, а не в <body> гарантирует, что все операторы будут просмотрены (и, в случае необходимости, выпол- выполнены) еще до того, как пользователь начнет взаимодей- взаимодействовать с документом. Не следует забывать и о том, чтс» помещение операторов сценария в раздел <body> доку- документа имеет массу опасных последствий. Даже зная конкретный список дескрипторов и поря- порядок построения документа, нельзя заранее гарантиро- гарантировать, будет ли пользователь взаимодействовать со сцена- сценарием предполагаемым способом или отреагирует на Web-страницу прежде, чем сценарий полностью загру- загрузится или выполнится. В этом случае предполагаемый эффект не будет достигнут. (Кому нужна такая ситуация после всех затраченных усилий?) Практика определения JavaScript-функций и затем вызов их из раздела <body> гарантирует, что все функ- функции оцениваются Прежде, чем пользователь начнет взаимодействовать с Web-страницей. Листинг 2.8 иллю- иллюстрирует эту практику, а листинг 2.9 показывает альтер- альтернативный путь. Листинг 2.8. Вызов функции. _ <html> <head> <title>Page with Pushbutton</title> <script type="text/javascript"> function pushbutton () { alert < "pushed") ; J // —> </script> </head> <body> <form> < input type=" SUBMIT" name="BUTtCONl" value="POSH" onclick="pushbutton ()"> </form> </body> </html> Листинг 2.9. Помещение JavaScript-сценария непосредственно в обработчик событий onclick. <html> <head> <title>Page with Pushbutton</title> </head> <body> <form> <input type="SUBMIT" name="BUTTONl" value="PUSH" onclicfc="alert('pushed')"> </forra> </fcody> </html> Листинг 2.9 демонстрирует возможность помещения операторов JavaScript непосредственно в дескрипторы HTML. Соотнесем недостатки этой практики с принци- принципами написания кода, о которых было сказано ранее. Изменение и многократное использование кода в деск- дескрипторах затруднено. Требуется найти дескриптор и за- затем вырезать и вставить код. Только тогда его можно будет многократно использовать или преобразовать в вызовфункции.
Совместная работа JavaScript и HTML Удобочитаемость и простота модификации как не- непосредственно для вас, так и для последующих разработ- разработчиков, также существенно снизится, если JavaScript-опе- JavaScript-операторы для функций не поместить в раздел <head>. Бесконечные поиски кода, который на самом деле отыскивается легко, в конце-концов выведут из душев- душевного равновесия даже самого терпеливого. Стили столь же важны в JavaScript, как и в любом другом языке программирования. Сохранение строгос- строгости стиля, своевременное определение переменных и ак- аккуратность форматирования в будущем сократят время разработки документов. Создавая сценарий JavaScript, функцию за функци- функцией, кусочек за кусочком, можно сформировать устойчи- устойчивые интерактивные документы, которые будут обладать большими функциональными возможностями. Посколь- Поскольку JavaScript интерпретируется, но не компилируется, процесс отладки не всегда полностью прозрачен. Мно- Множество проблем или ошибок не будет очевидно до тех пор, пока документ не подвернется серьезному тестиро- тестированию. Я бы рекомендовал, чтобы кто-то другой вместо разработчика занялся тестированием Web-страницы для ¦большей уверенности, что учтены абсолютно все ситуа- ситуации. Выполнение сценариев Глава 2 обходимости явно вызывать код. Поскольку код разме- размещается в HTML-документе или вызывается в первой строке сценария, сценарий будет выполняться во время загрузки Web-страницы. Помните, что сразу же после загрузки не обязательно выполняется весь код. Код, свя- связанный с вызовом функции, при загрузке Web-страни- Web-страницы только оценивается, но не выполняется до тех пор, пока функция не вызывается явно в результате генери- генерирования JavaScript-события. Код, не связанный с вы- вызовом функции, выполняется после полной загрузки Web-страницы, но до того как пользователь получит воз- возможность взаимодействовать с ней. Резюме Очевидно, что JavaScript столь же просто загрузить, как и НТМ L-документ. Для выполнения сценариев нет не- Очевидно, что хотя язык написания сценариев JavaScript и не зависит от HTML, оба они тесно связаны, если речь идет о проектировании, написании и выполнении до- документа в полном объеме. Код JavaScript можно запи- записывать непосредственно в коде HTML, расширяя таким образом текущие возможности Web-документов. Код просматривается и загружается вместе с HTML. Усовершенствования, постоянно появляющиеся в самом HTML, увеличивают функциональные возмож- возможности JavaScript-кода. Это позволяет улучшить доку- документы, сделать их более интерактивными и дружествен- дружественными по отношению к пользователю.
Создание собственного набора инструментальных средств JavaScript В ЭТОЙ ГЛАВЕ Необходимые инструментальные средства Процесс разработки на JavaScript Серверные инструментальные средства JavaScript Подобно любому языку разработки, JavaScript тре- требует определенную среду проектирования. В то время как язык Java связан со интегрированной средой разра- разработки (IDE) Symantec's Visual Cafe, для JavaScript по- подобного рода среда недоступна. Благодаря изобилию Web-инструментов, можно скомпоновать собственный набор инструментальных средств. В данной главе под- подробно исследуются различные доступные инструмен- инструментальные средства разработки кода как для клиентской, так и для серверной сторон. Необходимые инструментальные средства Перед началом разработки все необходимые инструмен- инструментальные средства потребуется скомпоновать. Например, при создании приложений в Delphi, Visual Basic, VisualAge for Java набор инструментальных средств, ско- скорее всего, будет относительно невелик, поскольку упо- упомянутые визуальные инструменты уже содержат все не- необходимое для работы. Однако это не относится к JavaSctipt. Для создания среды разработки потребуют- потребуются следующие основные инструментальные средства: • JavaScript-редактор для написания сценариев HTML-редактор для создания страниц Web-браузер для тестирования сценариев и приложе- приложений Отладчик сценариев для обнаружения ошибок JavaScript-редакторы Выбор редактора для разработчиков программного обеспечения равносилен выбору клюшки хоккеистом. Поскольку универсального рецепта не существует, рас- рассмотрим краткий обзор средств написания JavaScript- кода; возможно, это окажет необходимую помощь при выборе из множества текстовых, HTML- и JavaScript- редакторов. Текстовые редакторы Поскольку JavaScript-код располагается внутри HTML- страниц, то для эффективной разработки потребуется текстовый редактор. Если говорить о Windows, то реко- рекомендуется воспользоваться TextPad (рис. 3.1) или Notepad. Разработчики, установившие у себя I ni> мо- могут задействовать один из редакторов ешах или vi, а для пользователей Macintosh вполне неплохим пыбором будет SimpleText или BBEdit, показанный на рис.3.2. Использование стандартного текстового редактора обладает своими преимуществами — соответствующее программное обеспечение на компьютере уже установ- установлено. РИСУНОК 3.1 В качестве JavaScript-редактора можно использовать TextPad.
Создание собственного набора инструментальных средств JavaScript Глава 3 Среды разработки для JavaScript РИСУНОК 3.2 На компьютерах Macintosh наилучшим редактором для разработки кода на JavaScript no праву считается BBEdil. Разумеется, есть и свои недостатки, главный из ко- которых связан с отсутствием возможности изучения JavaScript и его расширений (например, библиотек ко- кодов или мастеров). Перед выбором из нескольких вариантов стоит вы- выяснить, какие функции реализует тот или иной редак- редактор. Например, наличие команд поиска и замены, в осо- особенности тех из них, что выполняют поиск по шаблону, записываемому как регулярное выражение. Следует отдавать предпочтение редакторам, которые обеспечивают цветовое представление синтаксиса. В таких случаях гораздо проще различать код, HTML и комментарии. С учетом перечисленных соображений TextPad явно выигрывает у Notepad. Будучи более функциональными, текстовые редак- редакторы TextPad и BBEdit позволяют разрабатывать в сво- своих средах и другие коды. При написании кода на HTML, JavaScript и даже на Java, можно использовать одни и те же инструментальные средства. Кроме того, HTML- редакторы от независимых разработчиков, наподобие Allaire HomeSite, обеспечивают дополнительную под- поддержку процесса разработки приложений на JavaScript. За счет использования единой среды исчезает необ- необходимость задействования множества программных па- пакетов и, следовательно, уменьшается количество прило- приложений, которые требуется изучить. Некоторые из :т^пных редакторов, помимо прочего, допускают интеграцию с Web-браузерами, обеспечивая быстрый просмотр и тестирование страниц и сценариев. РЕСУРС Web-сайт компании Allaire находится по адресу http://www.allaire.com. ¦ Помимо текстовых, существует и несколько редакто- редакторов, ориентированных исключительно на разработку JavaScript-сценариев. Первым таким редактором на рынке стал ScriptBuilder, разработанный компанией NetObjects. He желая терять позиции на рынке, компа- компания Netscape создала собственный продукт Visual JavaScript, позволяющий создавать в его среде целые Web-приложения. Впоследствии его функциональность практически полностью была перенесена в Application Builder. Общая функциональность подобного рода приложе- приложений включает в себя: • Применение технологии перетаскивания (drag-and- drop) для редактирования текста • Применение технологии перетаскивания для поме- помещения в текст дескрипторов HTML • Применение технологии перетаскивания для работы с методами и свойствами объектов • Выделение синтаксиса для ключевых слов JavaScript и дескрипторов HTML •• Функции поиска и замены ¦• Интеграция с распространенными браузерами для тестирования и отладки кода ПРИМЕЧАНИЕ Испытательную версию NetObjects ScriptBuilder мож- можно выгрузить из сайта NetObjects по адресу http:// www.netobjects.com. Не следует рассматривать перечисленные выше ин- инструментальные средства в качестве замены HTML-ре- HTML-редактора — лучше, чтобы они использовались в компо- композиции с ним. HTML-редакторы Дабы не забыть о самой природе среды разработки, добавьте в свой набор инструментальных средств HTML-редактор. Цели такого редактора заключаются не в создании сценариев, но в дизайне HTML-страниц, к которым позже будет добавляться JavaScript-код. Разли- Различают два вида HTML-редакторов — текстовые и визу- визуальные. В зависимости от пользовательских вкусов и предпочтений, выбирается тот или иной редактор, а иногда и оба. Текстовые HTML-редакторы Как обсуждалось ранее в главе, текстовые HTML-редак- HTML-редакторы реализуют среду, которая позволяет работать с дескрипторами HTML. Текстовые редакторы HTML не пытаются скрыть все детали дескрипторов. Наоборот, ¦они обеспечивают поддержку всего процесса разработ-
Знакомство с JavaScript Часть I ки кода на HTML, что существенно повышает их эффек- эффективность по сравнению со стандартными текстовыми редакторами. Визуальные HTML-редакторы Другой тип рассматриваемых редакторов — это HTML- редакторы, скрывающие от разработчиков детали гипер- гипертекстового языка форматирования страниц за счет обес- обеспечения визуальной среды (WYSIWYG — What You See Is What You Get), которая генерирует HTML-коды "за кулисами". В нынешнем компьютерном мире, где все так или иначе основывается на графике, процесс созда- создания страниц сводится к действиям типа "указать и щел- щелкнуть". Компания Netscape располагает визуальным HTML- редактором, который носит название Composer и встро- встроен в продукт Communicator. Composer позволяет редак- редактировать HTML-документы в рамках интегрированной среды браузера (см. рис. 3.3). Несмотря на то что ви- визуальная среда Composer позволяет работать с базовой разметкой HTML-страниц, все же должная поддержка визуальной работы с мультифреймовыми окнами, сти- стилями, и пр. обеспечивается явно не достаточно. РЕСУРС Последнюю информацию о Netscape Composer мож- можно найти на Web-сайте компании по адресу: htfp:// home.nefscape.com. Как только Mozilla.org выпустит первую версию Communicator с открытым кодом, она станет доступна по адресу http://www.mozilla.org. Отличительной особенностью еще одного подобно- подобного рода инструментального пакета Microsoft FrontPage является сложность. Однако этот пакет включает в себя, пожалуй, наиболее удачный визуальный HTML-редак- HTML-редактор. Редактор FrontPage Editor поддерживает не только расширенные возможности (например, наборы фреймов и таблицы), но содержит и наборы шаблонов, суще- существенно ускоряющих разработку Web-страниц. This is Netscape Composer! РИСУНОК 3.3 Composer компании Netscape. FrontPage представляет собой нечто большее, неже- нежели просто редактор. Он позволяет создавать админи- администрировать полновесный Web-сайт, рассчитанный на работу под управлением Microsoft Internet Information Server (IIS). РЕСУРС Актуальная информация по FrontPage находится по ад- адресу http://www.microsolt.com. Один из недостатков, присущих в настоящий мо- момент некоторым визуальным HTML-редакторам, связан с невозможностью перехода в текстовый режим и редак- редактирования чистого кода HTML. В текущей версии Composer потребуется прибегнуть к услугам какого-то внешнего редактора. Кроме ГОГО, Composer не знает, что делать с кодом JavaScript, поэтому не вздумайте исполь- использовать его в качестве среды редактирования кода, в ко- котором встречаются сценарии JavaScript. HTML-редак- HTML-редактор всего лишь позволяет быстро создать HTML, а затем при помощи текстового или JavaScript-редакторн не- несложно добавить сценарии. Web-браузеры Следующий необходимый компонент — Web-браузер, поддерживающий JavaScript (см. главу 1). Поскольку различные виды браузеров обеспечивают разную под- поддержку языка JavaScript, то во время тестирования по- потребуются многие из них, если не все. Основное правило гласит: сценарии необходимо те- тестировать во всех доступных браузерах. Для приложе- приложений, рассчитанных на работу в интрасети, достаточно' ограничиться всего лишь одним браузером. Однако со- создавая Internet-приложения, следует не забывать, что доступ к сайту, созданному с использованием JavaScript, могут получить браузеры практически любого iiiu Самый лучший способ выяснить, в каких браузерах просматривается ваш сайт предполагает анализ журна- журнала посещений Web-сайта. Все браузеры отправляют строку, определяющую тип браузера и установленную у пользователя операционную систему: • Истинные JavaScript-браузеры: Netscape Navigator 4.0+ и Microsoft Internet Explorer 4.0+ ¦• Ранние версии JavaSript-браузеров: Netscape Navigator 2.0, Netscape Navigator 3.0 и Internet Explorer 3.0 '• Другие браузеры, поддерживающие JavaScript: HoUava 3+, Opera 3+ и NetPositive 2.1 + • Браузеры, не поддерживающие JavaScript Создаваемое JavaScript-приложение необязательно должно поддерживать все браузеры. Например, может потребоваться использовать функцию, которая появи-
Создание собственного набора инструментальных средств JavaScript лась в последней версии Netscape Navigator, поэтому просматривать страницу необходимо именно в этой вер- версии браузера. С другой стороны, тестирование резуль- результатов проделанной работы в браузерах предыдущих вер- версий приносит несомненную пользу в плане расширения применимости. Отладчики сценариев Последний необходимый элемент в наборе инстру- инструментальных средств — отладчик. На данный момент существуют два основных отладчика, выпущенные ком- компаниями Microsoft и Netscape. Наверняка, захочется заг- загрузить оба отладчика, в результате чего появится воз- возможность организовать отладку как в браузере Navigator, так и в браузере Internet Explorer. В главе 34 оба отлад- отладчика рассматриваются более подробно. Процесс разработки на JavaScript Итак, все необходимые инструментальные средства со- собраны. Теперь их потребуется скомпоновать в среду разработки. Давайте вначале разберемся в самой систе- системе разработки приложений. На рис. 3.4 показан типо- типовой сценарий, в соответствие с которым начинают с создания базовых HTML-страниц, а затем добавляют JavaScript-код. После этого страница тестируется в выб- выбранном Web-браузере. HTML-редактор Создание HTML-страниц, Разработка JavaScript-редактор Добавление кода на JavaScript Итеративный процесс Web-браузер Отображение HTML-страниц, Тестирование/ Отладка РИСУНОК 3.4. ПроцеССразработки на JavaScript. Серверные инструментальные средства JavaScript Возможности, которые заложены в язык JavaScript, по- позволяют отнести его к языкам сценариев, входящим в состав инструментальных средств Web-разработки для сервера. Среди последних можно выделить Netscape's Глава 3 Server-Side JavaScript и Borland IntraBuilder. Чуть ниже приводится краткий обзор упомянутых инструменталь- инструментальных средств. Netscape's Server-Side JavaScript Server-Side JavaScript (SSJS) — реализация JavaScript для серверной части, созданная компанией Netscape. SSJS поддерживает серверные языковые объекты для доступа к файлам, почтовым сообщениям и базам дан- данных. SSJS может применяться для разработки пользо- пользовательских сценариев, запускаемых на сервере Netscape, что уменьшает потребность приложений в CGI-сцена- риях. Более подробная информация находится в гла- главе 12. . ресурс ,:;-: 1: Постоянно обновляющуюся информацию, связанную с Server-Side JavaScript, лучше всего отслеживать на странице Netscape DevEdge по адресу http:// developer.netscape.com. Borland IntraBuilder Borland IntraBuilder — среда визуальной разработки при- приложений, предназначенная для создания, поддержки и администрирования Web-приложений баз данных. Если когда-нибудь доводилось сталкиваться с инструменталь- инструментальными средствами визуальной разработки под Windows, то особых проблем с IntraBuilder возникать не должно. Ha Web-сайте компании Borland (ныне Inprise) всегда можно отыскать актуальную информацию касательно технического обслуживания и поддержки IntraBuilder. Адрес этого сайта таков: http://www.borland.com. Язык программирования, реализованный в рамках среды IntraBuilder, представляет собой расширенную версию JavaScript, которая характеризуется полной под- поддержкой объектно-ориентированной методологии (включая наследование) и наличием объектов доступа к базам данных. Если вы когда-либо работали с Borland Visual dBase, то найдете у этих сред множество общих черт. Резюме В данной главе были рассмотрены основные вещи, не- необходимые каждому разработчику: JavaScript-редактор, HTML-редактор, Web-браузер и отладчики сценариев. Кроме того, упоминались два известных серверных про- продукта, использующие JavaScript в качестве встроенного языка программирования.
Создание первого сценария В ЭТОЙ ГЛАВЕ Краткое напоминание Перед началом работы Приступаем к созданию сценария Первый сценарий Три предыдущих главы были посвящены JavaScript в контексте пространства Internet. Исследовались воз- возможные способы использования языка и его взаимосвязь с HTML. Упоминались проблемы поддержки языка со стороны браузеров, а также его реализация для сторо- стороны сервера. Была представлена информация о методи- методике написания кодов и всех необходимых инструмен- инструментальных средствах. Сейчас приступим к реализации первого сценария. Для начала необходимо выбрать правильный подход. Под правильным подходом подразумевается начальное планирование сценария, его разработка и тестирование. Перед переходом к собственно созданию сценария сто- стоит вспомнить некоторые вещи, рассмотренные в преды- предыдущих главах. требуется перевести компьютер в режим ожидания, пока не произойдет что-то совершенно определенное. Краткое напоминание Во-первых, вспомните, что JavaScript внедряется в HTML-документы через пару открывающих и закрыва- закрывающих дескрипторов <script>. После загрузки страницы браузер начинает интерпретировать код, начиная с от- открывающего дескриптора сценария <script> и завершая закрывающим дескриптором </script>, JavaScript интерпретирует каждую строку кода в ко- команды, которым затем и следует. Это очень похоже на выполнение определенных инструкций для приготовле- приготовления, скажем, жаркого. Вы читаете каждое указание и выполняете его, приближаясь к заветному результату (то бишь, жаркому). Точно так же и JavaScript выполняет все в строгом порядке. Пребывая на пути создания чудесного ужина, вы остановитесь, ожидая, скажем, разогрева плиты. Подоб- Подобного рода остановы воспроизводит и JavaScript, если Перед началом работы Перед написанием кода необходимо принять несколь- несколько решений, которые будут рассматриваться в следую- следующих разделах. Какие браузеры будут поддерживаться? Так каким же браузерам отдать предпочтение? Этот вопрос очень важен. Все зависит от объема создаваемо- создаваемого кода. Как упоминалось ранее, с момента выпуска первой версии JavaScript существенно изменился. До стандар- стандарта ECMAScript JavaScript был чуть ли не единственным подобного рода языком. ECMAScript определяет толь- только базовую часть языка, поэтому все, что касается сер- серверной и клиентской части, остается неизведанным. Какие браузеры потребуется поддерживать? Формируя ответ на этот вопрос, следует учесть не- несколько рекомендаций: • Обладает ли сервер функциональными возможностя- возможностями определения типа браузера перед отправкой ему страницы? • Имеется ли общая тенденция отказа от браузеров, которые не планируется поддерживать? Помощь со стороны сервера Если можно определить, какие браузеры запрашивают страницу перед ее отправкой, то это предоставляет оп- определенные преимущества при создании клиентских JavaScript-программ и сценариев. Опять-таки, это позво-
Создание первого сценария лит избежать ошибок на стороне клиента, которые свя- связаны с отправкой неподдерживаемого кода. Правда, потребуется создать несколько версий сце- сценариев, но время загрузки браузера существенно умень- уменьшится, а вероятность появления ошибки — снизится. Исчезнет необходимость определения типа пользова- пользовательского браузера и, соответственно, передачи лишних строк кода. Подобного рода функционирование позво- позволит плавно управлять известными неподдерживаемыми браузерами. Постепенные сбои Другой вопрос заключается в том, насколь последова- последовательно планируется поддерживать He-JavaScript-браузе- ры. Сюда относятся не только браузеры, вообще не под- поддерживающие JavaScript, но и браузеры с отключенной поддержкой JavaScript. ¦ ; : ПРЕДУПРЕЖДЕНИЕ В окне настройки предпочтений браузера обработка кода JavaScript может быть отключена. На рис. 4.1 показано окно настроек Navigator 4.7 и соответству- соответствующий флажок. Об этом очень важно помнить, по- поскольку придется учитывать и отключенную поддерж- поддержку JavaScript. Для простоты воспринимайте браузер с отключенным JavaScript как браузер, вообще не под- поддерживающий JavaScript. ii. tAaA г.. N&wsqrcups Н-Иааттц Аглае я -Cecha ¦ EmnrtUpdislR Г Sand i i пли FTP cojfwoi t 71 пв bafn'tt Ufqcifr'.. 3 РИСУНОК 4.1. Отключение поддержки JavaScript e Navigator4.7. Первым делом было бы неплохо для себя выяснить, какое место хочется занять в Internet-пространстве. Вы планируете создать сайт, который будет доступен всем людям на планете? Может быть, вы создаете интрасеть для компании и знаете, какие браузеры будут у пользо- пользователей? А, возможно, вы замахнулись на создание сайта для проверки возможностей JavaScript? Глава 4 Все, что потребуется определить, так это ограниче- ограничения, накладываемые на будущих пользователей. Акку- Аккуратно продумайте свое решение. Оставляя кого-то за бортом, вы тем самым снижаете потенциальный трафик. Если принято решение пользователей с не-JavaScript- браузерами не поддерживать, задача упрощается — их не придется обеспечивать дополнительным HTML-ко- HTML-кодом для просмотра страниц. Если же вам дорог любой пользователь (в том числе и тот, кто по ряду причин работает в He-JavaScript-браузере), постарайтесь предо- предоставить им настолько большую функциональность, на- насколько это в ваших возможностях. Как следует учитывать браузеры, не поддерживающие JavaScript? Самое время посмотреть, как же поддерживать просмотр страниц в браузерах с отключенной или вообще отсут- отсутствующей поддержкой JavaScript. Конечно, можно вос- воспользоваться функциональностью серверной стороны, о которой упоминалось ранее. Однако, она не поддер- поддерживает браузеры с отключенной поддержкой JavaScript. Здесь на выручку может прийти дескриптор <noscript>. Дескриптор <noscript> позволяет определить HTML- код, который будет отображаться на экране в случае,, ¦если JavaScript отключен или не поддерживается. Эта часть кода всегда следует после любого раздела <script>.. Листинг 4.1 демонстрирует один из примеров исполь- использования этого дескриптора, а рис. 4.2 — результат ото- отображения примера в Navigator 4.7 при отключенном JavaScript. What is returned? JavaScript is tamed offl 1 i РИСУНОК4.2. Визуализациядескриптора <noscript>. Листинг 4.1. Использование дескриптора <noscript>. <html> <head> <meta http-equiv="Content-Script-Type" content="text/javascript">
Знакомство с JavaScript Часть I <title>My First JavaScript Script</title> </head> <body> <hl>What is returned?</hl> <script> < ! — document.write ( '<p>JavaScript is turned II—> </script> <noscript> <p> JavaScript is turned off!</p> </noscript> </body> </html> Детально исследуя листинг 4,1 и рис. 4.2, несложно заметить, что в разделе <noscript> пользователю выво- выводится сообщение, гласящее что JavaScript отключен. Если же поддержка JavaScript включена, та же страни- страница интерпретирует код на JavaScript и игнорирует раз- раздел <noscript>. Дескриптор <noscript> поистине неза- незаменим при учете Не-JavaScript-браузеров. Некоторые устаревшие браузеры, например, Navigator 2 и ранние версии Internet Explorer, дескриптор <noscript> не воспринимают. Кроме того, ваш по- покорный слуга неоднократно имел честь наблюдать проблемы отображения в браузерах с отключенным JavaScript, когда данный дескриптор на странице ис- использовался более одного раза. Кажется, эти пробле- проблемы в большей степени относятся к семейству браузе- браузеров Navigator. Встроить код или вынести его в отдельный файл? Последний вопрос, который следует решить перед на- началом составления кода, — как размещать его на страни- странице. Предполагается, что вы уже располагаете функция- функциями, переменными и пр., которые требуется разместить в рамках действия дескриптора <head>. Весь вопрос в том, поместить ли код во внешний файл (.js) и сослаться: на него в атрибуте src дескриптора <script>, либо же разместить код непосредственно в документе. Как упоминалось ранее, в результате помещения кода во внешний файл можно будет редактировать один файл и воздействовать сценарием на все страницы. Сам я предпочитаю размещать все функции во внешних файлах. Зачастую я даже компоную функции по груп- группам и помещаю их в отдельные файлы. Например, один файл, calculations.js, может содержать функции расче- расчетов, а другой, formathandling.js, — различные операции форматирования. |ПРИМЕЧАНИЕ ^ Атрибут src появился только в JavaScript 1.1, .Это зна- значит, что полная его поддержка обеспечивается толь- только браузерами Navigator 3+ и Internet Explorer 4+. Предпринимались попытки обеспечить должную поддер- поддержку внешних сценариев и в Internet Explorer 3.02, од- однако результаты нельзя считать успешными. Каковы ваши цели? и Перед началом выполнения проекта исключительно важно определить преследуемые цели. Далеко не всегда этот этап проделывается должным образом. Так сложи- сложилось, что многие программисты смотрят на задачу раз- разработки сценария с позиций развлечения, а не с функци- функциональной точки зрения. Java Script обеспечиваетширокий простор для развле- развлечений, и если это для вас главное — нет проблем, впе- вперед и с песней! Если же на первом месте у вас стоит функциональность, попытайтесь минимизировать при- присутствие лишнего кода, ни для чего кроме показухи не предназначенного. По истечении определенного време- времени другие разработчики, да и вы тоже, убедятся, что отслеживать такой код становится сложнее и сложнее. Подумайте о дополнительных накладных расходах при внесении изменений в код, который в большей степе- степени "крутой", нежели функциональный. Выделяя цели, как можно более полно определите конечные результаты будущей программы. Например, может потребоваться проверка ошибок при заполнении форм пользователями. Поставив эту цель, потребуется вернуться обратно и определить способы ее достиже- достижения. Если программа должна содержать форму, задай- задайтесь вопросами, сколько элементов будет находится на форме, т.е. сколько переключателей, текстовых полей, флажков и т.п. После преодоления второго уровня целей можно приступать к проблематике кодирования сценария. Потребуется реализовать код для поддержки переклю- переключателей, текстовых полей и флажков. Можно создать функцию, получающую параметр (скажем, radio), ко- которая возьмет на себя всю необходимую обработку. Не забывайте о повторном использовании кода — исклю- исключительно полезная штука, когда требуется уменьшить объем создаваемого кода, да, собственно, и воспользо- воспользоваться накопленными знаниями и опытом. Приступаем к созданию сценария Вы готовы к написанию кода. Решено, какие браузеры будут поддерживаться, а какие — нет, как работать с не- неподдерживаемыми браузерами и где хранить сценарии.
Создание первого сценария Глава 4 Определение целей В первом сценарии будет создаваться простой всплыва- всплывающий диалог, запрашивающий у пользователя пароль. В случае ввода пользователем некорректного пароля вы- выполняется переход на страницу, отображающую соот- соответствующее сообщение. Если введенный пароль — правильный, пользователь перенаправляется на запра- запрашиваемую страницу. Для браузеров, не поддержива- поддерживающих JavaScript, отображается сообщение о невоз- невозможности доступа к странице. Поскольку сценарии реализуются на самом общем подмножестве операторов JavaScript, они будут корректно выполняться в любом JavaScript-браузере. Кроме того, все сценарии будут встраиваться, а не выноситься во внешние файлы. Рассмотрим резюме вышеизложенного: ¦• Поддержка браузеров: Поддерживать все браузеры ¦ • Реакция нане-JavaScript-браузеры: отобразить сооб- сообщение о невозможности доступа к данной части ва- вашего сайта Размещение сценария: встроенный • Цель: Запросить у пользователя пароль перед досту- доступом к странице. При вводе корректного пароля пользователь направляется на защищенную страни- страницу, а в противном случае — на страницу, уведомля- уведомляющую сообщение об ошибке. Создание шаблона кода После выяснения целей рекомендуется приступить к созданию шаблона. Когда я занимаюсь такого рода ве- вещами, я помещаю в него всю необходимую информа- информацию раздела <head> и готовлю часть, касающуюся <body>. В листинге 4.2 показан типовой шаблон, с ко- которого можно начать. Листинг 4.2. Файл шаблона JavaScript. <htnvl> <head> <meta http-equiv="Content-Script-Type" content="text/j avascript"> <title>nepBWf сценарий на JavaScript</title> <script language="JavaScript"> // Здесь следует поместить код на JavaScript <Jscript> </head> <body> <!— Здесь начинается код содержимого страницы —> </body> </html> Учет He-JavaScript-браузеров Сначала необходимо выяснить, как относиться к бра- браузерам, поддержка которых не планируется. Листинг 4.3 демонстрирует подход, выбранный для данного примера. Листинг 4.3. Работа с неподдерживаемыми браузерами. <body> <noscript> <b> Извините, используемый вами браузер либо не поддерживает JavaScript, либо упомянутая возможность отключена. Информацию, связанную с поддержкой браузером JavaScript, равно как и с включением/отключением э^ой поддержки, можно отыскать на сайте компании- разработчика браузера. </noscript> </body> Несложно заметить, что все действия сводятся к выдаче на экран простого сообщения. Текст помещен между парой дескрипторов (<b>...</b>), что обеспечи- обеспечивает его отображение в полужирном начертании. Написание кода Все вопросы, связанные с внешним видом и функцио- функциональностью страницы, решены. Можно перейти к на- написанию кода. За счет предварительного решения всех моментов, связанных с определением целей, созданием шаблона, учетом неподдерживаемых браузеров появи- появилась уверенность, что страница должна функциониро- функционировать нормально и без написания кода. Этот несомнен- несомненно важен, поскольку зачастую ошибки возникают не по> причине некорректного написания сценария, но из-за неправильно записанного кода HTML или присутствия комментариев не на своих местах. Основная работа в данном примере выполняется в разделе <head>. Первым шагом будет создание диало- диалогового окна ввода пароля. Для этого используется ме- метод prompt, в результате вызова которого отображается диалоговое окно, как на рис 4.3, обеспечивающее пере- передачу введенной пользователем информации в сценарий. В i Qfef Ueai Prompt 0 iUrr ,* * F*pr JJrt - ' I'* t I РИСУНОК4.3.Диалоговоеокноprompt. Ключевой момент, связанный с использованием окна, заключается в том, что оно возвращает информа-
Знакомство с JavaScript Часть I цию, введенную пользователем. На основе упомянутой информации можно протестировать, привел ли ввод корректного пароля к переадресации на требуемую страницу. prompt — это метод объекта window, воспринимаю- воспринимающий два параметра и имеющий такой синтаксис: prompt("message","default"); При вызове этого метода потребуется заменить message на строки, инструктирующие пользователя. Они будут отображаться над полем ввода данных. Па- Параметр default определяет для поля ввода значение по умолчанию. В нашем первом сценарии значение по умолчанию не предусматривается, поэтому в метод пе- передается пустая строка. В дополнение к методу prompt используется свой- свойство location объекта window, позволяющее перенапра- перенаправить браузер на соответствующую страницу в зависимо- зависимости от введенного значения. И последнее, что еще осталось — поместить код в функцию, вызываемую пос- после загрузки страницы. Код, реализующий данную задачу, достаточно неве- невелик (см. листинг 4.4). Листинг 4.4. Запрос ввода пароля. <script language=" JavaScript"> <!-- function passCheckO { if(prompt("Пожалуйста, введите пароль","") = '""letmein") { window.location = "/secure.html"; }else{ window.location = "/error.html"; I } II—> </script> В листинге 4.4 в дескриптора <script> используется атрибут language. Поскольку в шаблоне определено Content-Script-Type в дескрипторе <meta> в разделе <head> документа, нет необходимости повторно зада- задавать язык в дескрипторе <script>. Далее рассматривается процесс создания функции passCheck(). В теле этой функции для проверки пароля, введен- введенного пользователем, используется условный оператор if..else. He стоит беспокоиться о том, как он работает. Данный аспект детально рассматривается в главе 7. Следует лишь понять, что данная конструкция прове- проверяет, вводится ли в качестве пароля последовательность letmein ("ну дайте же войти"). Проверка осуществляет- осуществляется с использованием операции ==, которая подробно рассматривается в главе 6. В результате ввода корректного пароля пользователь перенаправляется на страницу /secure.html. Если же пароль оказывается некорректным, браузер отображает страницу /error.html. Вызов функции Последний шаг в построении работоспособного сцена- сценария — вызов функции. В данном случае сие действие организуется через обработчик событий onLoad непос- непосредственно после загрузки страницы. Данный обработ- обработчик событий определяется в виде атрибута дескрипто- дескриптора <body>: <body onload="passCheck()"> 'Первый сценарий Сценарий готов, осталось лишь собрать его в единый документ. В листинге 4.5 показана полная страница так, как она выглядит в текстовом редакторе. Листинг 4.5. Окончательный сценарий. <html> <head> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>nepHbtti сценарий на JavaScript</title> <script language="JavaScript"> <! — .function passCheck {) { if (promptf "Пожалуйста, введите "пароль","") == "letmein") ( window, location = "/secure.html",- >else{ window . location= " /error. html " ; i </script> </head> <body onload="passCheck() "> <noscript> <b> Извините, используемый вами браузер либо не поддерживает JavaScript, либо упомянутая возможность отключена. Информацию, связанную с поддержкой браузером JavaScript, равно как и с включением/отключением этой поддержки, можно отыскать на сайте компании- разработчика браузера. </noscript> </body> </html> Из листинга несложно заметить, что в дескрипторе <head> определяются используемый по умолчанию язык и функция, которая вызывается через атрибут дес- дескриптора <body>. Для неподдерживаемых браузеров предусматривается дескриптор <noscript> в части <body> страницы. На рис. 4.4 показан результат выпол- выполнения сценария в JavaScript-браузере, а на рис. 4.5 — в He-JacaScript-браузере.
Создание первого сценария РИСУНОК 4.4. Результат выполнениякода излистинга 4.5в JavaScript-браузере. i Ш Ш ШЯЬиШ IbRiiiniTp, пспользуемып вами браузер либо не поддерживает JavaScript, либо упомянутая возможность отключена, Ипформяцшо, связанную с поддержкой браузером JavaScript, равно как и с включением/отключением этой поддержки, можно отыскать ня сайте komi Р И СУ Н О К 4.5 Результат выполнения кода из листинга 4.5 в не-3а vaScript-браузере. Глава 4 Резюме Эта глава была посвящена реализации самого первого сценария. Примите поздравления. Конечно, можно было бы составить сценарий типа "Hello World", одна- однако хотелось предоставить нечто большее. Сценарий "Hello World" сводится, всего-навсего, к вызову метода document.write() в разделе <body> документа. Вы уже умеете это делать в результате написания первого сце- сценария. Данная глава завершает первую часть книги. Следу- Следующие части предоставляют дополнительную информа- информацию по JavaScript. Мы вместе углубимся в синтаксис и семантику языка.
Базовое подмножество языка JavaScript ЧАСТЬ В ЭТОЙ ЧАСТИ 5. Основы языка JavaScript 6. Операции 7. Управляющие структуры и организация циклов. 8. Функции 9. Объекты со стороны клиента 10. Основные объекты языка 11. Создание пользовательских объектов JavaScript 12. Серверная часть JavaScript
Основы языка JavaScript В ЭТОЙ ГЛАВЕ Краткое резюме Взаимосвязь JavaScript с Java, CGI и подключаемыми модулями Встраивание сценариев в HTML-документы События Синтаксис JavaScript — высокоуровневый объектно-ориентиро- объектно-ориентированный язык, при помощи которого Web-дизайнеры и программисты легко и просто создают интерактивные Web-документы. Он обладает характеристиками объек- объектно-ориентированного языка, не имея сложных функ- функций, столь характерных для Java и C++. Несмотря на свой относительно небольшой и легко воспринимаемый словарный запас, возможностей у JavaScript очень много. Данная глава посвящена осно- основам языка и его взаимосвязи с двумя известными Web- технологиями. Ближе к концу главы можно найти ис- исчерпывающую информацию, необходимую для создания собственно сценариев. Краткое резюме Пока компания Sun разрабатывала хваленый язык про- программирования Java, Netscape трудилась над созданием упрощенного языка сценариев LiveScript. Позже, пос- после внесения существенных изменений, язык был пере- переименован на JavaScript и совместно выпущен компани- компаниями Stn и Netscape. С помощью JavaScript обеспечивается практически неограниченная интерактивность Web-страниц, т.к. он дает возможность доступа к таким событиям, как за- запуск, загрузка документов, выход и нажатие кнопки мыши. JavaScript применяется при прямом контроле ¦объектов, таких, как браузерная строка состояния, фреймы, и даже, браузерное экранное окно. JavaScript, также, обеспечивает интерактивность между дополни- дополнительно вставляемыми модулями и Java-аплетами. Как JavaScript связан с CGI, дополнительно вставляемыми модулями и Java Любого вполне может заинтересовать, что может пред- предложить JavaScript при использовании CGI-программ и подключаемых модулей такого, чего не умеет делать Java. Благодаря CGI-программам полуинтерактивные Web-страницы появились еще до рождения JavaScript. Позже появились подключаемые модули и Java, придав- придавшие Web-страницам еще большую интерактивность. Бо- Более подробное рассмотрение этих технологий обеспечит лучшее понимание вклада JavaScript в рамки набора ин- инструментальных средств создания Web-страниц. CGI CGI — стандартный интерфейс между программами и Web-сервером. Используя языки программирования, такие как Perl, C/C+, Visual Basic или AppletScript, и применяя стандарт CGI, можно создавать программы, передающие информацию от клиента на Web-сервер. Например, многие поисковые утилиты, обеспечива- обеспечивающие нахождение тех или иных Web-сайтов и необхо- необходимой информации, создавались в соответствие со стан- стандартом CGI. Пользователи вводят ключевое слово или фразу в текстовом элементе HTML и щелкают на кноп- кнопке Search. Введенный текст передается на сервер, кото- который запускает CGI-программу. В свою очередь, про- программа получает входные параметры и выполняет соответствующие функции. Поиск будет выполняться через основную базу данных, выдавая в качестве резуль-
Базовое подмножество языка JavaScript Часть II тата только те сайты, которые отвечают заданному критерию поиска. После завершения операции поис- поиска CGI-программа генерирует новый HTML-документ с результатами, который и отправляется в Web-браузер пользователя. В данном случае вся основная работа выполняется сервером. В том случае, когда имеется возможность со- создавать только статические Web-страницы, приходится учитывать все возможные комбинации поиска. Созда- Создание Web-документов на каждый запрос было бы непрак- непрактично, это крайне неудачный способ эмуляции привыч- привычных поисковых механизмов. Рассмотренное относится к одной из проблем, решенных при помощи CGI, и это помогло Web стать более интерактивной средой. ресурс1 ¦- :"¦" "¦'¦ .''¦¦" '¦': ¦¦ "'"'' Практически всю известную информацию по стандар- стандарту CGI и существующим CGi-сценариям можно найти по адресу http://hoohoo.ncsa.uiuc/edu/cgi/overview.hlml. Подключаемые модули После щелчка на ссылке браузер генерирует запрос на загрузку файла. Если файл хранит простой текст, HTML или графику, он отображается на экране. В слу- случае когда браузер не может распознать файл, он пред- предлагает сохранить его на жестком диске или выбрать приложение для его обработки. Аналогичные моменты возникают и тогда, когда файлы различных форматов внедряются в тело одного HTML-документа. Подключаемые модули, впервые представленные в Navigator 2.0 и Internet Explorer 3.0, существенно рас- расширили количество файлов, распознаваемых браузером. Подключаемые модули представляют собой программы, применяемые для расширенной обработки файлов (ска- (скажем, отображение их на экране с дополнительными способами управления) либо для интерпретации фай- файлов, невозможной в оригинальной версии браузера. К упомянутым файлам относятся аудио-, видео-, Acrobat - и VRML-файлы. Например, щелчок на ссылке, указывающей на аудио- аудиофайл, в браузере, не поддерживающем данный формат, Таблица 5.1. Сравнение Java и JavaScript. приведет к поиску соответствующего подключаемого модуля. После загрузки этого модуля начинается про- проигрывание клипа. Интеграция браузера и аудиопроиг- рывателя — практически бесшовна. иРЕСУРС ¦¦ ' ¦ ^ ' .>¦ • f: , *>-.¦ . ;.. Огромный список подключаемых модулей можно отыс- отыскать на сайте компании Netscape по адресу http:// home.netscape.com/download. Java Java — технология, более всего напоминающая JavaScript. Однако значительные отличия все же существуют. Да- Давайте немного подробнее рассмотрим Java, как это было с CGI и подключаемыми модулями. В отличие от JavaScript, Java не имеет встроенного механизма прямого доступа к элементам (т.е. объектам) Web-страницы. Стоит отметить отсутствие клиентской версии, которая могла бы управлять HTML- и другими объектами. Структура и синтаксис Java весьма близки к JavaScript. Зарезервированные слова, операции и опе- операторы управления потоком данных совершенно иден- идентичны. Поскольку Java — компилируемый язык, на кодовые конструкции накладываются более высокие требования. Существенные отличия Java от JavaScript имеют место в двух ипостасях: правилах типизации переменных и методологии инкапсуляции, принятой для классов. В табл. 5.1 сведены различия между JavaScript и Java: В JavaScript переменные и функции объявляются локально или глобально. Java обеспечивает условие гиб- гибкого многоуровневого доступа к переменным и методам (функциям), когда упомянутые элементы представля- представляются вместе с модификаторами доступа: private, protected и public. Модификаторы позволяют скрывать атрибуты объекта и детали разработки от общего доступа к объек- объекту, предоставляя большую степень свободы в модифи- модификации кода. В данном случае несложно поддерживать опубликованный интерфейс объекта и в то же время обеспечивать обратную совместимость. JavaScript Java Язык написания сценариев Слабый контроль типов Рудиментарный доступ Отсутствие порожденных типов Отсутствие контроля доступа к массивам Иерархия экземпляров JavaScript-объекты Язык программирования Строгий контроль типов Многоуровневый доступ Объектно-ориентированные возможности и наследуемые атрибуты Строгий контроль доступа к массивам Объектная иерархия Java-классы
Основы языка JavaScript Глава 5 Переменные экземпляров Java должны объявляться строго, причем каждой определенной переменной дол- должно присваиваться значение ее основного или производ- производного типа. Коды JavaScript, наоборот, не требуют спе- спецификации. JavaScript имеет встроенные типы данных, основная задача которых связана с оптимизацией пове- поведения и размеров переменных. Еще одна особенность JavaScript связана с более обобщенной классификационной схемой (number или string) no сравнению с Java (int, long, float или char). В то время как объекты JavaScript нельзя эффективно преобразовать в более сложные объектные типы, в Java имеется возможность создания классов, группирующих переменные в объектные компоненты. ПРИМЕЧАНИЕ Следующая предлагаемая версия JavaScript (скорее всего, это будет 2.0) будет обладать более строгой классификацией элементов. В JavaScript 2.0 было пред- предложено добавить такие типы, как int, long, float и char. JavaScript вполне можно посчитать объектно-ориен- объектно-ориентированным языком, поскольку он поддерживает иерар- иерархию экземпляров. В нем имеется возможность опреде- определять объекты, содержащие методы и переменные, организовывать ссылки в соответствие с точечной нота- нотацией; единственное, чего нельзя сделать — расширять объекты, используя механизм порождения подклассов. Хоть синтаксис Java и напоминает синтаксис JavaScript в отношении ссылок и создания объектов, все же Java является истинным языком программирования, смахи- смахивающим на C++. При использовании Java-кода определения объектов могут послужить оболочкой при создании более слож- сложных архитектур. Объектные классы — это кирпичики, из которых строится Java-код. В отличие от JavaScript, каждая функция и переменная Java должна определять- определяться внутри какого-то класса. Более того, Java позволяет группировать классы в пакеты взаимосвязанных объек- объектов, равно как и определять абстрактные интерфейсные соглашения для заданных категорий объектов. ¦Следующее отличие связано с тем, что разработчик компилирует исходный код Java в байт-коды, создавая двоичные компоненты, которыми могут воспользоваться другие программисты. На основе полученных компонен- компонентов (т. г. классов объектов) создаются производные клас- классы, наследующие функциональность и расширяющие атрибуты базовых классов. Возможность расширения базового класса является основой концепции повторного использования кода в сложных приложениях, что существенно повышает эф- эффективность программ. Строгий контроль типов обес- обеспечивает Java-компилятор, который требует от програм- программиста явного объявления и приведения переменных экземпляров либо к встроенным, либо к производным типам. С другой стороны, JavaScript разрешает програм- программисту прозрачно переключать определитель типа пере- переменной без учета первоначального определения типа. Два языка настолько тесно взаимосвязаны, что это позволяет разработчикам внедрять вызовы JavaScript- функций в код на Java, а также обеспечивать доступ к методам Java-классов из JavaScript. Упомянутые воз- возможности увеличивают ценность тех программистов на JavaScript, которые обладают определенными знани- знаниями Java. Данная технология известна под именем LiveConnect, Основные аспекты этой технологии под- подробно рассматриваются в главе 25. Внедрение сценариев в HTML-документы Одна из необычных сторон JavaScript связана с тем, что на этом языке можно создавать программы, работающие как со стороны сервера (см. главу 12), так и со стороны клиента, т.е. в среде браузера. С клиентской стороны JavaScript применяется в соответствие с одним из двух способов: внедрение в HTML-документ между парой дескрипторов <script> либо помещение внутрь дескрип- дескриптора для обеспечения реакции на событие. Каждый раз когда HTML-страница загружается, JavaScript интерпре- интерпретируется браузером. В зависимости от действий пользо- пользователя и других событий, могущих возникнуть во вре- время просмотра HTML-документа, выполняется сценарий целиком или его части. Например, разрабатывается HTML-документ для сбора данных о посетителях определенной Web-страни- Web-страницы. Начать стоит с формы, содержащей три текстовых элемента: имя, название компании и номер телефона. В конец формы можно поместить стандартную кнопку Submit (Отправить) для отправки информации в базу данных, размещенную на Web-сервере. Кроме того, можно потребовать, чтобы пользователь полностью за- заполнял каждое поле, а вместе с номером телефона ука- указывал код города. После щелчка на кнопке Submit все данные формы передаются на обработку в серверную часть программы. Если оказывается, что пользователь опустил какую- либо информацию, выдается запрос на ввод этих дан- данных. Затем пользователь может отправить форму, вклю- включающую требуемые данные, к тому же в корректном формате. После того как программа получит от пользо- пользователя удобоваримые данные, она сохраняет их в базе данных. Поддержка полей, обязательных для заполнения, как в данном случае, приводит к существенным задержкам, которых можно избежать при помощи JavaScript. Име- Имеет смысл организовать проверку всех данных на клиен-
Базовое подмножество языка JavaScript Часть II ТСКОЙ части • - этим не должен заниматься Web-сер- Web-сервер. Реализация проверки данных — всего лишь один из примеров того, как JavaScript может дополнять сервер- серверные программы, обеспечивая более быструю реакцию на ошибки и при этом освобождая большее количество' ресурсов на сервере. В главе 14 вопросы, связанные с проверкой данных, рассматриваются более подробно. События Одна из ключевых характеристик JavaScript — возмож- возможность захватывать ограниченное количество пользова- пользовательских действий, в большинстве случаев известных под именем событий (events). Некоторые HTML-элемен- HTML-элементы уже реагируют на события; примером может послу- послужить щелчок на хорошо известном элементе ссылки, что приводит к перенаправлению на другой HTML-доку- HTML-документ. Как только указатель мыши попадает на соответству- соответствующий ссылке текст или графическое изображение, ука- указатель изменяет свой стандартный вид стрелки на вид указующей руки. В дополнение к этому, некоторые браузеры отображают в строке состояния новый URL. В JavaScript подобного рода действие носит название события MouseOver, и реакция будет иметь место тог- тогда, когда возникает любого рода движение мыши поверх элемента. После щелчка на любой части ссылки брау- браузер обеспечивает переход на соответствующий Web-ад- Web-адрес либо открытие нового файла. Описанное действие называется событием Click, которое будет генерировать- генерироваться в результате любого щелчка на ссылке. HTML пере- перехватывает эти события, и точно такой же будет реакция браузера. При помощи JavaScript можно обеспечить пользова- пользовательские реакции на многие события, генерируемые во время просмотра HTML-документа пользователем. Осо- Особенностям управления событиями полностью посвяща- посвящается глава 14. Синтаксис Как и в любом языке программирования, в JavaScript определены собственные способы управления различ- различными элементами. Разумеется, в языке присутствует своя специфика представления ключевых слов, зарезер- зарезервированных слов, символов и т.п. Версии JavaScript В результате неутомимой совместной деятельности ком- компаний Netscape, Microsoft и ряда других, призванной усовершенствовать стандарт ECMAScript, появились но- новые версии JavaScript и поддерживающих этот язык бра- браузеров. В данной книге речь идет, в ОСНОВНОМ, о версии 1.4, а иногда и о версии 1.5, находящейся на стадии бета- тестирования. Таблица 1.5 предоставляет исчерпываю- исчерпывающую информацию о поддерживаемых платформах. Таблица 5.2. Поддержка JavaScript. Версия Описание JavaScript 1.0 Поддерживается в Netscape Navigator 2 JavaScript 1.1 Поддерживается в Netscape Navigator 3, Internet Explorer 3, Opera 3, Netscape Enterprise Server 2 JavaScript 1.2 Поддерживается в Netscape Navigator (версии 4-4.04), Internet Explorer 4 JavaScript 1.3 Поддерживается в Netscape Navigator (версии 4.05-4.7), Internet Explorer5 JavaScript 1.4 Поддерживается в альфа-версиях Moziila <до М 12), HotJava 3.0, Internet Explorer 5.5, Netscape Enterprise Server 4.6 JavaScript 1.5 Планируется поддержка в Navigator 5 (Moziila), т.е. в версии Netscape Navigator с открытым кодом. Внимательное исследование табл. 5.3, 5.4 и 5.5 позво- позволит понять взаимосвязь существующих версий JavaScript, JScript и ECMAScript. Таблица 5.3. Взаимосвязь между JavaScript и JScript. JavaScript JScript 1.0 1.1 1.2 ¦1,3 ¦и 1.5 Не соотносятся 1.0-2.0 3.0^.0 5.0-5.1 5.0-5.1 5.5 Таблица 5.4. Взаимосвязь между JavaScript и ECMAScript. JavaScript ¦1.0 11.1 1.2 1 1 -14 'I 5 ECMAScript He соотносятся He соотносятся — Фундамент для стандарта Не соотносятся — Большая часть перенята из ECMAScript 1.0 1.0 1.0 B-я модификация) 1.0 C-я модификация)
Основы языка JavaScript Глава 5 Таблица 5.5. Взаимосвязь между JScript и ECMAScript._ JScript 1.0 2.0 3.0-3.1 4.0 5.0 5.5 ECMAScript Не соотносятся Не соотносятся — Фундамент для стандарта 1.0 1.0 1.0 B-я модификация) 1.0 C-я модификация) Каждый разработчик JavaScript должен хорошо знать особенности целевой платформы, чтобы выбрать для разработки корректную версию JavaScript, т.е. то, что потребуется указать в атрибуте language дескриптора <script>. ПРИМЕЧАНИЕ ..'¦"¦ - ': Не следует забывать, что дескриптор <script> в HTML 4.01 и XTML 1.0 был официально упразднен. На дан- данный момент стандартного дескриптора, позволяюще- позволяющего определить языковую версию, не существует. Пока нет никакой определенности, я бы посоветовал вос- воспользоваться атрибутом language в композиции с ат- атрибутом type. Например, если приложение должно работать в Netscape Navigator 2 и выше, а также в Microsoft Internet Explorer 3.0, сценарии следует разрабатывать на JavaScript 1.0. Однако если выходной платформой является Navigator 5.0/Mozilla, и есть желание воспользоваться всеми преимуществами новой версии языка, то для ука- указания версии 1.5 следует записать: <script language="JavaScriptl.5" type="text/javascript"> Для версии 1.4 воспользуйтесь такой строкой: <script language = "JavaSeriptl.4" type="text/javascript"> А для версии 1.3 -такой: <script language= "JavaScriptl.3" type="text/javascript"> Для версии 1.2 подойдет строка: < script language= "JavaScriptl.2" type="text/javascript"> Выбор версии 1.1 обеспечит строка: <script language="JavaScriptl.1" type="text/javascript"> А версии 1.0 — строка: <script language="JavaScript" type="text/javascript"> ИрймечАнйе ",-"-, " •'"'"' \ ¦' ¦ s*" •¦; и.. ¦; PJL 'Ц Не пытайтесь в качестве выбранной версии 1 .0 языка указывать "JavaScriptl.0" или "JavaScriptl". Подобно- Подобного рода сентенции не распознаются, и в результате сценарий игнорируется. ^ВНИМАНИЙ Перед переходом к исследованию особенностей язы- языка JavaScript хотелось бы снова напомнить о важности указания корректного языка в дескрипторе <script>. Браузер попросту проигнорирует любой сценарий, для которого определяется нераспознанная им версия языка. Лексемы Лексемы (tokens) — это наименьшие отдельные слова, фразы, символы, которые может распознать JavaScript. Во время интерпретации JavaScript-кода браузер разби- разбивает сценарии на лексемы, игнорируя при этом коммен- комментарии и лишние пробелы. Лексемы подразделяются на четыре категории: иден- идентификаторы, ключевые слова, литералы и операторы. Как и в любом компьютерном языке, существует мно- множество способов подачи компьютеру различных дирек- директив за счет различной компоновки лексем. Синтаксис (syntax) языка — это набор правил и ограничений, ис- используемый при комбинировании лексем. Идентификаторы Идентификаторы (identifiers) — суть ни что иное как име- имена переменных, методов и объектов. Они состоят из комбинации букв и цифр. Некоторые имена уже встро- встроены в язык JavaScript и поэтому зарезервированы от использования. Независимо от ключевых слов, можно определять собственные, притом значащие идентификаторы. Разу- Разумеется, для этого существует несколько правил: ¦ • Все идентификаторы должны начинаться либо с бук- буквы, либо с символа подчеркивания (_). • Для всех последующих знаков допускается исполь- использование букв, цифр и символов подчеркивания. В понятие букв входят заглавные буквы, начиная с А и заканчивая Z, и строчные буквы, т.е. с а до z. Имя идентификатора не должно содержать пробелов. В понятие цифр входят знаки, начиная с 0 и закан- заканчивая 9. В табл. 5.6 показаны примеры допустимых и недо- недопустимых идентификаторов.
Базовое подмножество языка JavaScript Часть II Таблица 5.6. Примеры идентификаторов JavaScript. Допустимые Недопустимые current_WebSite numberOfHits in N current WebSite #oflslands 2bOrNotToBe return Идентификатор current WebSite является недопусти- недопустимым по причине присутствия в нем символа пробела. Этот идентификатор будет рассматриваться не как один,, но как два. Если по смыслу в идентификаторе должен находиться пробел, то на его месте обычно ставится символ подчеркивания. #oflslands не является допустимым, поскольку сим- символ # не входит в разрешенное множество символов. 2beOrNotToBe — некорректен, потому как начинается с цифры. Идентификатор return уже используется в JavaScript для других целей. В случае его определения, после запуска приложения выдается ошибка. Идентификаторы п и N — вполне допустимы, одна- однако отличны друг от друга. Ввиду того что JavaScript чувствителен к регистру, упомянутые идентификаторы интерпретируются как разные, даже несмотря на их, в общем-то, одинаковое произношение. Ключевые слова и зарезервированные слова Ключевые слова (keywords) — предварительно определен- определенные идентификаторы, составляющие ядро языка про- программирования. В JavaScript они выполняют особые функции, например, объявление новых переменных, функций, принятие решений на основе текущего состо- состояния компьютера или организация цикла внутри при- приложения. Ключевые слова встроены в JavaScript и всегда дос- доступны программисту, однако в отношении них следует придерживаться правильного синтаксиса. Ключевое слово var — одно из первых, о котором будет детально рассказываться в главе. Позже демонстрируется приме- применение других ключевых слов для создания более дина- мичныхпрограмм. Зарезервированные слова (reserved words) — это иден- идентификаторы, которые не могут использоваться в каче- качестве имен переменных, функций, объектов и методов как сейчас, так и в будущем. Рассмотрим полный спи- список зарезервированных слов JavaScript: abstract else instanceof switch boolean enura int synchronized break export interface this byte extends long throw case false native throws catch final new transient char class const continue debugger default delete do finally float for function goto if implements imoort null package private protected public return short static true try typeof var void volatile while with Литералы Литералы (literals) — это числа или строки, представля- представляющие постоянные значения JavaScript. Это значения, которые не изменяются во время выполнения сценария. В следующих пяти разделах рассматриваются различные виды литералов. Целочисленные литералы Целочисленные литералы могут быть представлены в десятичном (десятичная система счисления), восьме- восьмеричном (восьмеричная система счисления) или шестнад- шестнадцатиричном (шестнадцатиричная система счисления) формате. Целочисленный литерал в десятичном форма- формате может содержать любую последовательность цифр, но не начинаться с 0. Ноль в начале целочисленного литерала определяет восьмеричный формат. В восьмеричной записи целочисленный литерал может включать последовательность цифр от 0 до 7. Для определения шестнадцатиричного формата числа перед литералом должно ставится Ох или ОХ. Шестнадцати- Шестнадцатиричные целочисленные литералы могут содержать циф- цифры от 0 до 9 и буквы а — Гили А — F. Рассмотрим не- несколько примеров: Десятичные литералы: зз, 2139 Восьмеричные литералы: cm, 03664 Шестнадцатиричные литералы: 0x7Ь8, 0X395 Литералы с плавающей точкой Литералы с плавающей точкой представляют десятич- десятичные числа с дробной частью. Их можно выражать в стандартном и экспоненциальном форматах. Экспонен- Экспоненциальный формат подразумевает использование е или Едля определения порядка числа. И десятиричное чис- число, и показатель степени могут быть со знаком или без- беззнаковыми (положительные и отрицательные): 3405.673 -1.958 8.3200е+11 8.3200е11 9.98Е-12
Основы языка JavaScript Логические литералы В JavaScript реализован логический тип данных, поэто- поэтому поддерживаются два литерала true и false, представ- представляющие соответственно значения логической 1 и 0. Если вы новичок в области программирования, не отчаивай- отчаивайтесь — очень скоро вы поймете всю важность true и false. Ключевые слова true и false должны записываться строч- строчными буквами. Таким образом, TRUE и FALSE пропис- прописными буквами остаются доступными для применения в качестве собственных идентификаторов. Однако, во избежание недоразумений, использовать их в таком контексте не рекомендуется. Строковые литералы Строковый литерал — это ноль и более символов, зак- заключенных в двойные ("") или одиночные (") кавычки. Несмотря на то что JavaScript разрешает использовать оба типа кавычек, для строки лучше применять один и тот же тип кавычек как в начале, так и в конце. Рассмот- Рассмотрим примеры строковых литералов: "Allen's car" 'virtual "communities"' "#12-6" "Look, up in the sky!" Применение одного из двух видов кавычек достаточ- достаточно удобно, если вы — сторонник либо первого, либо второго метода. Во время изучения встроенных методов JavaScript следует учесть необходимость строгого выпол- выполнения всех указаний, касающихся строковых литералов, передаваемых в качестве параметров. В ряде случаев допускается применять оба типа кавычек при помеще- помещении одного строкового литерала внутрь другого. После- Последнее не разрешается при указании управляющих кодов, речь о которых идет ниже. Специальные символы Иногда в сценарии может потребоваться использовать специальный знак либо их комбинацию, например, симвох табуляции или новой строки. В этом случае уп- управляющий код должен предваряться символом наклон- наклонной черты влево (\), как показано ниже: \Ь — забой \f — перевод страницы — новая строка \г — возврат каретки \t — табуляция \\ - наклонная черта влево V — одинарная кавычка \" — двойная кавычка Глава 5 Если требуется сэмулировать нажатие клавиши та- табуляции для выравнивания, скажем, двух столбцов данных, следует использовать знак табуляции (\t). В листинге 1.5 демонстрируется один из способов вырав- выравнивания текста при помощи знаков табуляции. Если сценарий содержит специальные знаки, читать его ока- оказывается сложнее, но как показано на рис. 5.1, резуль- результаты выглядят гораздо лучше: Листинг 5.1. Использование специальных знаков в JavaScript. <html> <head> <^Ъ1е>Специальные символы в JavaScript- сценариях</ЫЫе> </head> <body> <! Специальные символы не возымеют действия до vex пор, пока не поместить их в сформатированный блок текста (т.е. тот, который находится между парой дескрипторов <рге>..</рге>). <рге> <script type="text/javascript"> document.writeln("\tPersonnel") ; document.writeln("Name\t\tAddress"); document.writeln("Jeff\t\tjeff@company.com") document.writeln("Bill\t\tbill@company.com") document. writeln("Kim\t\tkim@company.com"); </script> </pre> </body> </html> Bill Kim bill@cbmpany.com fdia@.;omp?ny, com 'РИСУНОК 5.1. Выравнивание текста при помощи табуляции. ПРИМЕЧАНИЕ Специальные знаки оказывают воздействие только ког- когда используются в пределах предварительно отформа- отформатированного текстового блока, потому-то сценарий дол- должен помещаться в пару дескрипторов <рге> и </рге>. Если строковый литерал должен воспроизводить сим- символы кавычек, применяйте их в паре с символом наклон- наклонной черты влево.
Базовое подмножество ЯЗЫКп JavaScript Часть II document.write("\"*антаэия важнее знаний.\""); document.write(", Альберт Эйнштейн"),- Этот сценарий обеспечит отображение на экране следующей строки: "Фантазия важнее знаний.", Альберт Эйыптейн Операции Операции (operators) — это символы или идентификато- идентификаторы, которые представляют способ оценки или манипу- манипуляции комбинациями выражений. Наиболее использу- используемой общей операцией является далеко не операция присваивания. В примере х=10 как собственно 10, так и переменная х — это выражения. Когда JavaScript встречает операцию присваивания между двумя выра- выражениями, выполняются действия в соответствие с пра- правилами оператора присваивания. В рассматриваемом случае значение выражения в правой части присваива- присваивается переменной в левой части. Наряду с арифметичес- арифметическими, JavaScript поддерживает 30 других операций, которые более подробно рассматриваются в главе 6. Переменные Переменная (variable) — это имя, присваиваемое ячейке памяти компьютера, которая хранит определенные дан- данные. Праотцы программирования тратили уйму време- времени на трансляцию данных, наподобие сообщения "Hello World", в двоичные коды. Затем они искали свободное место в компьютерной памяти для размещения всех полученных единичек и ноликов, не забывая запомнить адрес начала и завершения этих данных. При помощи упомянутых адресов ячеек памяти можно было нахо- находить, изменять и считывать данные. В общем, никогда не завершающийся день сурка. (Да здравствует День Сурка!!!) Нынешним программистам повезло больше — им на помощь пришли переменные, и жизнь их пошла на су- существенную поправку, поскольку сохранение, измене- изменение и чтение данных стало теперь как никогда простым. Благодаря механизму переменных появляется возмож- возможность присваивать значащие имена ячейкам, которые хранят данные, явно используемые программистом, в то время как доступ к остальным ячейкам — забота исклю- исключительно компьютера. Проблема именования Имя переменной в JavaScript состоит из одной и более букв (A..Z и a..z), цифры @..9) и символов подчеркива- подчеркивания (_). однако не может начинаться с цифры. Следу- Следующих два имени JavaScript воспринимает как различ- различные: internetAddress internetaddress Вот еще корректные имена: _lastName л number_2 Когда имя переменной по смыслу содержит одно слово, при ее записи принято использовать строчные буквы, а вот при наличии в имени смысловых двух или трех слов, то первое слово начинается со строчной, а все последующие — с прописных. Обычно мои имена пе- переменных заключают в себе два-три слова, что обеспе- обеспечивает гораздо лучшее понимание смысла определения переменной. Предположим для примера, что требуется перемен- переменная с логическим значением (true or false), которая уве- уведомляет, завершил ли посетитель Web-страницы ввод своего имени в текстовом поле. Если имя переменной выглядит наподобие finish, другой программист с удив- удивлением подумает: "Что это — флаг, при помощи кото- которого можно выяснить, завершены ли пользовательские действия? А, может быть, это — строковое выражение, которое записывают после того, как посетитель завер- завершил операцию, скажем, сообщение о благодарности?" В данном случае гораздо лучшим выбором будет имя isDone. Использование в качестве приставки слова is позволяет рассматривать переменную как вопрос, на который требуется ответ "да" или "нет", а это, в свою очередь, означает, что переменная хранит логические значения. Если посетитель завершил ввод своего имени, isDone присваивается значение true, в противном слу- случае false. Несмотря на то что размер имени переменной JavaScript ограничивается только объемом оперативной памяти, все же подходить к данному вопросу лучше с практической точки зрения. Я советовал использовать не более 20 символов, т.е. 2-3 слова. При написании сценария не стоит заходить за конец строки. Этому спо- способствуют длинные имена переменных, к тому же они нарушают целостность восприятия кода. По сложившейся традиции переменные, состоящие из одного слова и даже из одного символа, представля- представляют математические значения. Вот несколько примеров подобного рода имен: п для любого числа, х, у, z — для координат, i — для заполнителя в рекурсивной функции или переменной цикла. Поскольку данные способы — тра- традиционные, их можно использовать каждый раз, когда сочтете нужным. Работая в профессиональном окружении, потребу- потребуется обеспечить удобочитаемость написанного кода для других разработчиков. В этом смысле существенную помощь окажут непротиворечивые и осмысленные со- соглашения об именовании. Плохо или недостаточно про- продуманные соглашения ничего кроме головной боли не принесут, да и могут отрицательно сказаться на осно-
Основы языка JavaScript вополагающих показателях компании как разработчика программного обеспечения. Объявление переменных Для того чтобы уведомить JavaScript о том, что конк- конкретный идентификатор должен использоваться в каче- качестве переменной, в первую очередь, его потребуется объявить. Для объявления переменных в JavaScript ис- используется ключевое слово var, за которым следует но- новое имя переменной. Имя будет резервироваться как пе- переменная, которую можно использовать в качестве области памяти для хранения любых данных. Следую- Следующий пример демонстрирует возможность одновремен- одновременного объявления нескольких переменных (между от- отдельными именами должны ставится запятые). var internetAddress; var n; var i, j, k; var isMouseOverLink, helloMessage; После объявления переменной можно присваивать начальное значение. Подобное действие носит название инициализации и выполняется при помощи операцией присваивания =. Знак равенства (=) используется для присваивания пе- переменной определенного значения. Проблемы, связан- связанные с оператором присваивания, подробно рассмат- рассматриваются в главе 6. Переменную можно инициализировать непосред- непосредственно при ее объявлении либо позже, в любом месте сценария. Установка начального значения переменной во время объявления упрощает запоминание, какой тип значений первоначально планировалось хранить в пере- переменной. Уточним предыдущий пример, добавив необ- необходимые инициализации: var internetAddress = "name@company.com"; var n = 0.00 ; var i = 0, j = 0, k; var isMouseOverLink = false; var hello Message = "Hello, thank you for coming!"; k = 0; Несложно заметить, что все переменные, кроме к, были проинициализированы во время объявления, а к инициализируется позже. JavaScript читает строки кода сверху вниз, выполняя директивы одну за другой. До инициализации переменная остается неопределенной (undefined), поэтому прочитать ее значение нельзя. По- Попытка чтения значения переменной перед ее инициа- инициализацией приведет к ошибке во время выполнения при- приложения. JavaScript дает возможность проверить, было ли присвоено значение переменной, с помощью опера- оператора tj'peof (см. главу 6). Глава 5 В дополнение к ключевому слову var, JavaScript предлагает и другой способ объявления переменных при помощи обычной их инициализации. Если присво- присвоить новой переменной значение перед ее объявлением при помощи var, то JavaScript автоматически объявит ее. ^примечанйе^Г^^^'^^Ж'Т ^ ' '". " *¦"•¦?.. В ранних версиях JavaScript-браузеров объявление пе- переменных без слова var означало их автоматическое объявление с глобальной областью действия (или ви- видимости). Может возникнуть впечатление, что это сокращает накладные расходы, однако хорошая прак- практика программирования предполагает именно явное объявление переменных. При помощи ключевого слова var поддерживается концепция области действия переменной. Типы При сохранении порции данных (более известных под именем значения), JavaScript автоматически относит ее к одной из пяти категорий. В табл. 5.7 сведены различ- различные типы данных, поддерживаемые JavaScript. Таблица 5.7. Типы данных JavaScript. Тип Пример number boolean string function ¦object -19,3.14159 true, false "Элементарно, дорогой Ватсон","" unescape, write window, document, null Переменные типа number хранят действительные или целые числа, boolean — значения true или false, a string содержат строковые литералы, включая пустую строку. В табл. 5.7 пустая строка представляется с по- помощью двух двойных кавычек. Функциональный тип (function) либо определяется пользователем, либо отно- относится к встроенным функциям. Например, функция unescape является встроенной в JavaScript. Проблемати- Проблематике создания функций, определяемых пользователем, по- посвящается глава 8. Функции, принадлежащие объектам, в JavaScript называются методами (methods). Они также относятся к типу данных function. Базовые клиентские объекты JavaScript, такие как window или document, имеют тип данных object. Переменные типа object, или просто объекты, могут хранить объекты. Переменная со значе- значением null относится к типу object. Инициализация пе- переменной значением null позволяет избежать ошибок, если нет уверенности в будущем ее использовании. Как правило, в других языках программирования Требуется определять тип данных, представляемых но- новой переменной. На протяжении всей программы тип любого значения, присваиваемого переменной, должен
Базовое подмножество языка JavaScript Часть II быть определенным и неизменным. Более того, если переменной присваиваются значения различных ТИПОВ, это приводит к ошибке. Для JavaScript, слабо типизи- типизированного языка, подобное не имеет места. Не потре- потребуется определять типы данных. Кроме того, одной и той же переменной можно присваивать значения разных Типов. Переменная JavaScript способна в любой момент принять новое значение. Рассмотрим примеры допусти- допустимого использования переменных JavaScript: var carLength ; carLength =4+5; document.writeln(carLength); carLength = "9 футов",- document.writeln(carLength); После объявления переменной carLength ей присва- присваивается значение 4+5. В JavaScript число 9 сохраняется с типом number. Присваивая carLength значение друго- другого типа "9 футов", в этой переменной сохраняется стро- строковый литерал (string). Операция подобного рода уменьшает количество действий, которые могли бы по- потребоваться в других языках программирования для уведомления о факте смены типов значений. Область действия переменных Область действия (или видимости) переменных (scope) —¦ это участки внутри программы, в которых возможна ссылка на переменную. Например, рассмотрим случай внедрения одного сценария в часть <head> HTML-до- HTML-документа, а другого — в часть <body> того же докумен- документа. JavaScript считает, что все переменные, объявленные внутри упомянутых двух участков, принадлежат одной и той же области действия. Такие переменные являют- являются глобальными (global), и они доступны любому сцена- сценарию в текущем документе. Несколько позже речь пой- пойдет о функциях — отдельных блоках кода. Переменные, объявленные внутри таких блоков, носят название ло- локальных (local) и они доступны не каждому сценарию. Локальные переменные Переменная, объявляемая внутри функции является локальной. К значениям этой переменной может иметь доступ только данная функция. При каждом вызове функции все локальные переменные создаются, а пос- после возврата функции — разрушаются. Если в другой функции присутствует объявление переменной с таким же именем, она рассматривается как совершенно дру- другая переменная. Каждая из переменных адресует свой 'блок памяти. Глобальные переменные Если требуется, чтобы какая-то переменная совместно использовалась в более чем одной функции, следует объявить ее вне функций (но, конечно же, внутри пары дескрипторов <script>). В этом случае данная перемен- переменная будет доступна в любой части всего приложения, в том числе и во всех функциях. ^ПРИМЕЧАНИЕ Г Рекомендуется объявлять глобальные переменные в разделе <head> HTML-страницы, тем самым гаранти- гарантируя, что они загрузятся раньше любой другой части приложения. Листинг 5.2 демонстрирует способ объявления и применения глобальной переменной. Для большего понимания различий между областями действия пере- переменных, в программу помещены две функции. Не обя- обязательно выяснять, как действуют функции, следует лишь усвоить тот факт, что они представляют собой отдельные части сценария, заключенные в фигурные скобки ({}). Более подробную информацию, связанную с функциями, можно найти в главе 8. Листинг 5.2. Глобальные и локальные переменные. <html> <head> <title>JavaScript Unleashed</title> <script type="text/javascript"> <! — / / Глобальные переменные var globalString = "A"; // Функаии function changeToB() { document. outputForm. bef oreB . value = globalString; globalString = "B"; document.outputForm.afterB.value = globalString; 1 function changeToCf) { document. outputForm. bef oreC . value = globalString; globalString = "C"; document. outputForm. af terC. value = globalString; </script> </head> <body> <script type="text/javascript"> <! — document, write ("The initial value of ''•globalString is V" + globalString + "\".">; //--> </script> <br> <form name=" outputForm" >¦ <input name="changeButtonA" type="button" value="Change To B" onclick= "changeToBO ">
Основы языка JavaScript Глава 5 <input name="changeButtonB" type="button" value="Change To C" onclick="changeToC(>"> <p> Value of globalString <J» <input name="beforeB" type="TEXT" size=,l"> <P> Before clicking on "Change To <p> <input name="afterB" type="TEXT" size=,l"> <P> After clicking on "Change To B" <P> <input nanre="be?oreC" type="TEXT" size=,l"> <P> Before clicking on "Change To С <P> <input name="afterC" type="TEXT" size=,l"> <P> After clicking on "Change To C" </form> </body> </html> Первым отображается начальное значение globalString. Несмотря на то что переменная объявляется в разделе <head> документа, сценарий, расположенный внутри раздела <body> ее может использовать. Щелчок на кноп- кнопке "Изменить на В" приводит к тому, что функция change ТоВ() выводит на экран первоначальное значение globalString, заменяет его на В и отображает новое зна- значение globalString (см, рис. 5.2). i The initiii value ofglobalString is "A". Value of globsUSlring Before clicking он "Change To B" After clicking OD "Change To B" Before clicking on "Change To C" After clicking on "Change To C" РИСУНОК 5.2. Глобальные и локальные переменные. Для демонстрации гого, что все функции в докумен- документе могут использовать одну и ту же переменную, была добавлена вторая кнопка для вызова другой функции. Пс'сле щелчка на кнопке "Изменить на С", на экра- экране отображается текущее значение globalString, на дан- данный момент равное В, после чего значение globalString изменяется на С. На рис. 5.2 показаны результаты опи- описанных действий. Константы Константа представляет собой переменную, сохраняю- сохраняющую свое значение неизменным на всем протяжении выполнения программы. JavaScript использует встроен- встроенные константы для представления значений для обыч- обычных математических действий, скажем, число пи. Дос- Доступ к таким константам осуществляется через объект math (см. главу 10). Константы, определенные пользователем — это суть определенные пользователем переменные, значения которых не изменяются. Обычно при именовании кон- констант используются строчные буквы и они определяют- определяются в начале программы. JavaScript не поддерживает константы в традицион- традиционном смысле. В языках программирования, поддержива- поддерживающих константы, определяемые пользователем, никакая другая часть приложения не может изменять значение константы после его определения. Попытка подобного изменения приведет к ошибке. В JavaScript все по-ино- по-иному. Даже при отсутствии уверенности в том, что перемен- переменная не изменяется, все же стоит работать с переменными для сохранения значений, которые будут использоваться на протяжении всего сценария. Заменяя переменной множество вхождений простых значений, сценарий го- гораздо проще изменить впоследствии. Все что потребу- потребуется предпринять — изменить начальное значение пере- переменной и сценарий полностью обновится. Цвета JavaScript поддерживает цвета, используемые при созда- создании HTML-страниц. Доступные цвета в виде строковых литералов (не констант) сведены в табл. 5.8. Перечис- Перечисленные значения можно присваивать определенным свойствам объекта. В листинге 5.3 показано применение этих значений для установки цветов отображаемых строк. Допускается использование имени цвета либо его шестнадцатирич- шестнадцатиричного эквивалента. Хоть это может показаться странно- странноватым, однако выполняется только установка свойства fontcolor для отображаемого на экране строкового лите- литерала. Неплохо было бы внимательным образом изучить рис. 5.3. Нельзя изменить цвет текста, уже выведенного в окно браузера. В таком случае потребуется просто перезагру- перезагрузить документ с новым установленным цветом шрифта. Листинг 5.3. Использование цветов в JavaScript. <html> <head> ПРИМЕЧАНИЕ
Базовое подмножество языка JavaScript Часть II JavaScript</title> </head> <body> все из них поддерживаются JavaScript. В табл. 5.8 све- сведены все цвета, поддерживаемые JavaScript. <h2> <script type="text/javascript"> document.writeln( "Пикник для сотрудников .fontcolor("orimson")) ; </script> </h2> <h4> <script type="text/javascript"> document.writeln(9 июля в час "¦•дня" . fontcolor ( "blue") > ; document.writeln ("<br>" + "He забудьте *• захватит» свою семью!" .fontcolor ("#008000")) ; </script> </h4> </body> </html> Шестнадцатиричная строка для каждого цвета пред- представляет собой комбинацию значений RGB (red/green/ blue — красный/зеленый/голубой), лежащих в основе каждого цвета. Например, шестнадцатиричное значение для цвета морской волны (aqua) выглядит как #OOFFFF. В приведенном значении RGB: 00 — красный, FF — зе- зеленый и FF — голубой. Две цифры в шестнадцатиричном значении позволяют определять 256 оттенков каждого цвета. В цвете морской волны красная составляющая равна 0, а это означает отсутствие в нем красного цве- цвета. Интенсивности зеленого и голубого максимальны. Обеспечив соответствующие пропорции зеленого и го- голубого в результате приводят к цвету морской волны. Имея 256 комбинаций красного, синего и зеленого мож- можно скомпоновать около 16 миллионов цветов, однако не Пикш для сотрудников компании! 23 апреля в шесть в«ч*ра Не забудьте захватить семьи! РИСУНОК 5.3. Изменение цвета текста в JavaScript. Типы данных Несмотря на недавнее обсуждение основных типов дан- данных, присваиваемых переменным, стоит напомнить, что функции и объекты относятся к специальным типам данных. Они предлагают достаточно интересные спо- способы сохранения и манипулирования данными сцена- сценария. Особенности использования функций и объектов рассматриваются в главе 8. Выражения Выражение (expression) — это набор операторов, которые подобно группе объединяется в одно значение. Результи- Результирующее значение будет относиться к одному из следую- следующих типов данных: boolean, number, string, function, object. Таблица 5.8. Значения цветов с их шестнадцатиричными эквивалентами. Цвет Я G В Цвет R G В aliceblue aqua azure bisque blanchedalmond blueviolet buriywood chartreuse coral cornsilk cyan darkcyan darkgray darkkhaki FO 00 FO FF 8A DE 7F F:F \ DO 00 A9 BD F8 FF FF E4 EB 2B B8 FF 7F F8 Fl 8B A9 •;7 FF ;f Fl C4 CD F_2 87 00 SO IX. FF 8B A9 6B antiquewhite aquamarine beige black blue brown cadetblue chocolate cornflowerblue crimson darkblue darkgoldenrod darkgreen darkmagenta FA 7F F5 00 00 A5 5F D2 64 DC 00 B8 00 8B EB pp F5 00 00 2A ЭЕ 69 95 14 00 8G 64 00 D7 D4 DC 00 FF 2A АО 1E 'El ЭП 8B OB 00 HI
Цвет G Цвет Основыязыка JavaScript Глава 5 G е darkolivegreen darkorchid darksalmon darkslateblue darkturquoise deeppink dimgray firebrick forestgreeni gainsboro gold gray greenyellow Ihotpink indigo khaki lavenderblush llemonchiffon lightcoral lightgoldenrodyellow lightgray lightsalmon lightskyblue lightsteelblue lime linen maroon mediumblue rnediumpurple mediumslateblue mediumturquoise midnightblue mistyrose navajowhite oldlace olivedrab orangered palegoldenrod paleturquoise papayawhip peru plum. purple rosy brown saddlebrown sandybrown seashell 3 1-158 55 99 1: 9 48 00 FF 69 IB2 '22 DC FF 80' All FF 4B FO' 1 F IFF FO' IFA D3 iFF 87 IBO 00 IFA 80 00 93 7B 48 19 IFF ГР FD 6B !FF ЕЕ AF FF ¦CD on 80' ВС 8B IF4 FF 6B 32 96 SID CE 14 69 22 8B IDC D7 80' ГГ 69 00 E6 F0 li A 80 ГА to АО CE C4 FF FO' 00 00 7ft 68 D1 19 E4- DE IF5 8E 45 E8 ЕЕ ,EF 85 АО 00 8F 45 A4 F5 2F CC ТЛ 8B П 93 69 22 22 IDC 00 80 2F B4 82 8C F5 CD 80 02 D3 7A FA IDE 00 E6 00 CD DB IFF. CC 70 Ё1 AD E6 23 00 AA ЕЕ D5 3F DD 80 8F 13 60 ЕЕ darkorange darkred darkseagreeni darkslategray darkviolet deeps kyblue dodgerblue floralwhite fuchsia ghostwhite goldenrod green 'honeydew indianred ivory lavender lawngreen lightblue lightcyan lightgreen lightpink lightseagreen lightslategray lightyellow Ilimegreen magenta imediumaquamarine mediumorchid mediumseagreen mediumspringgreen mediumvioletred imintcream, moccasin navy olive orange orchid palegreeni palevioletred peachpuff pink powderblue red royalblue salmon seagreen sienna IFF 8B 8F 2F 94- 00 IE FF FF IF8 DA 00 F0' CD IFF E6 7C AD E0 90 Iff 20 77 FF 32 FF: 66 BA 3C 00 C7 F5 FF 00 80 rf DA 98 DB ,FF FF BO FF 41 FA 2Ё A0' 8C 00 IBC 4F 00 ,BF 90 ! A 00 F8 A5 80 FF 5C IFF E6 FC Bo FF ЕЕ B6 B2 88 FF CD 00 CD 55 B3 Га 15 JT E4 00 80 A5 70 IFB 70 DA CO' E0 00 69 80 8B 52 00 00 8F 4F 03 l F FF iO l_l_ FF 20 00 FO 5C 'FO II A, 00 f 6 FF 90 C1 AA 99 EO 32 FF AA O3 71 9A 85 FA B5 80 00 00 D6 98 93 B9 CB E6 00 П 72 57 2D
Базовое подмножество языка JavaScript' Часть II " Цвет R G В Цвет R silver slateblue snow steelblue teal tomato violet white yellow 1 0 ЪА FF 46 00 FF ra. IFF FF CO 5A ГЛ 182 80' 63 82 ,! F FF CO CD ГЛ Bl 80 47 1-Е FF CD skyblue slategray springgreen tan thistle turquoise wheat whitesmoke yellowgreen .87 70 00 D2 ID8 40 ! 5 F5 ?IA CE ,80 FF B4 BF li 0 D?; 1 5 CD II 90 7F 8C D8 DO B3 F5 32 Выражение может быть простым, как отдельное чис- число или переменная, а также включать в себя переменные, ключевые слова и операции. Например, выражение х=10 присваивает значение 10 переменной х. Приведенное выражение дает результат 10, потому применение вы- выражения в строке а-ля document.writeln(x=10) — впол- вполне допустимо. JavaScript мог бы рассматривать информацию, зак- заключенную в кавычки, как строку и просто отображать ее на экране, однако в данном случае выполняются не- некоторые дополнительные действия. Сначала рассчиты- рассчитываются все выражения, присутствующие в скобках, и только после этого осуществляется собственно отобра- отображение значения на экране. В рассматриваемом приме- примере на экран выводится 10. Кстати, просто х — тоже допустимое выражение. В данном случае выполняется только чтение значения переменной из памяти. Не выполняется ни одного при- присваивания. Разумеется, в выражениях можно применять великое множество других операций помимо операции присваивания (см. главу 6). Комментарии До сих пор дескрипторы комментария применялись только для окружения текста сценариев, что гарантиро- гарантировало отсутствие их отображения в старых браузерах. А как насчет воспользоваться комментарием, чтобы про- проигнорировать часть кода JavaScript? Оказывается, все сильно смахивает на C/C++ и Java: // Однострочный комментарий Две косых черты (//) "скрывают" текст вплоть до конца текущей строки. Допускаются и многострочные комментарии: /* Желаете поместить ¦строк? Так вот ааы и способ! */ комментарий несколько В обоих типах комментариев излишние пробелы иг- игнорируются, поэтому оба следующих примера коррект- корректны: // Комментарий /* Многострочный комментарий * / Листинг 5.4 демонстрирует применение обоих типов комментариев. Две косых черты не обеспечат сокрытие кода от старых браузеров. Дабы не создавать трудностей упомянутым браузерам, для обрамления сценариев про- продолжайте прибегать к паре <!-- и —>. Все, что в лис- листинге 5.5 закомментировано, на экране отображаться не будет (см. рис. 5.4). Листинг5.4.Использованиедескрипторов комментариев в JavaScript. JavaScript</title> <html> <head> <title>KoMMeHTapmi </head> <body> <script type=" text/ j avascript" > <! — // Переменные var ?irstName = "Jon" ; var lastName = "Simpson"; var internetAddress = "jsimpson@company.com"; Отобразить имя и фамилию пользователя вместе с его адресом электронной почты. // Скомбинировать три строки document .writeln (firs tName + " " + lastName + "<br>") ; document.writeln ("e-mail address: " + internetAddress); // —> </script> </body> </html> Возможность сокрытия определенного кода от ин- интерпретации JavaScript дает возможность документиро- документировать сценарии. Совсем неплохо по ходу пьесы добавлять заметки, связанные с дизайном, дружеские напомина- напоминания или предупреждения. Это окажет существенную
Основы языка JavaScript помощь для других в плане понимания, что означают те или иные разделы программы. Щ JavaScript Unleashed - Netscape ¦ - ^E -| tfj' Jon Simpson e-mail address: jsimpson@company.com РИСУНОК 5.4. Комментарии на экране браузера не отображаются. Глава 5 ПРИМЕЧАНИЕ Советую объявлять переменные в разделе <head> HTML-документа. Это позволит получить уверенность, что функция загрузится браузером до ее выполнения в разделе <body>. ¦ .¦ ¦ ¦ . ..¦ - ¦ . ..-¦¦ Для вызова функции достаточно поместить ее имя в любом месте программы. Главная программа размеща- размещается внутри раздела <body> и обрамляется парой деск- дескрипторов <script>. Результат использования функции показан на рис. 5.5. Листинг 5.5. Внедрение функции JavaScript. <html> <head> <title>Ilcncwb3OBai»ie функций в JavaScript</title> <script type="text/javascript"> <!-- function displayMessage() ( document.write ("Функции JavaScript ^исключительно просты в -использовании!<Ьг>"); Еще одно применение комментариев касается отлад- отладки сценариев. Для целей тестирования можно упрятать часть своего кода, а после его отладки с легкостью вер- вернуть, удалив всего лишь символы комментария. В отли- отличие от удаления частей сценария, такие действия суще- существенно экономят время. Функции В простейшей своей форме функции — это сценарии, вызываемые по имени в любой момент. Разумеется, они призваны серьезно расширить возможности JavaScript. После прочтения HTML-документа JavaScript-браузе- JavaScript-браузером, последний отыскивает все внедренные в документ сценарии и выполняет инструкции шаг за шагом. Все это очень удобно до тех пор, пока не потребуется, чтобы вся программа или ее часть перешла в режим ожидания. Организация такой части программы в виде поимено- поименованной функции — один из путей решения упомяну- упомянутой проблемы. После генерации определенных событий имеется возможность запустить сценарий, воспользовавшись именем, присвоенным функции. Другое преимущество функции связано с повторным использованием кода сценария. В листинге 5.5 показан один из способов использо- использования функций JavaScript. Первое, на что стоит обратить внимание— где будет объявляться функция. Объявлять следуе" не только переменные, но и функции. Не забудь- забудьте все объявления функций поместить в пару дескрип- дескрипторов <script>. </script> </head> <body> <script type="text/javascript"> <! — document. write < "Вызов функции *¦»JavaScript.. .<p>"); displayMessage(); document.write("</р>Сделано, // "> </scrip t> </body> </html> "); jij Hi* ¦ : ¦, Вызов функции JavaScript... Функции JavaScript исключительно просты в использовании! Вот и все, что было. »™; РИСУНОК 5.5. Вызов функции в JavaScript.
Базовое подмножество языка JavaScript Часть II Начав с главного сценария, JavaScript, как обычно, выполняет первую строку, а затем попадает на вызов функции dispIayMessage(). Выполняется поиск функ- функции в памяти и переход на ее первую строку. После вывода на экран фразы Функции JavaScript исключи- исключительно просты в использовании! отображается разрыв строки. Как только функция завершается, выполнение программы возобновляется с точки, где она приостано- приостановилась по причине обращения к функции. Как видно на рис. 5.5, каждая строка текста отобра- отображается в определенной последовательности. Если у вас громоздкая программа, несколько раз выводящая сооб- сообщение на экран, вызовы функции можно вставить в любых требуемых местах. Если позже потребуется из- изменить текст сообщения, это делается лишь в одном месте. Поменяйте его внутри тела функции, и прило- приложение полностью обновится. Преимущества использо- использования функций подробно описываются в главе 8. Резюме JavaScript сделал серьезный взнос в набор инструмен- инструментальных средств Web-разработчика. Именно в этом язы- языке доступны многие вещи, кажущиеся невозможными для CGI, подключаемых модулей и Java. JavaScript обес- обеспечивает взаимодействие с пользователем во время про- просмотра HTML-документа. Сценарии помещаются непосредственно в HTML- документы и обрамляются парой дескрипторов <script>. Для того чтобы JavaScript игнорировал отдельные части сценария, воспользуйтесь корректным типом коммента- комментариев. Интерпретатор JavaScript прочитывает каждую строку сценария, начиная с самой первой. Лексемы представ- представляют собой небольшие отдельные слова, фразы и знаки, доступные JavaScript. Лексемами могут быть литералы, идентификаторы и операторы. К доступным типам данных относятся: number, boolean, string, function и object. В один и тот же момент времени переменная может хранить данные только од- одного типа. Для объявления переменных либо восполь- воспользуйтесь ключевым словом var, либо просто проинициа- лизируйте переменную. Для повышения читабельности сценариев присваивайте переменным осмысленные имена. Выражение — это набор операторов, результатом выполнения которых является единственное значение. Наиболее типичные выражения сводятся к присвоению значений переменным. Операция присваивания = слу- служит для присваивания значения правого операнда пе- переменной, записанной как левый операнд. JavaScript поддержи
Операции В ЭТОЙ ГЛАВЕ Операции присваивания Арифметические операции ¦Операции сравнения Строковые операции Условные операции Булевы операции Операция typeof Определение и вызов функций Операции со структурами даннвгх Поразряднвю операции Приоритетв! ввшолнения операций Основной смысл написания сценариев связан с не- необходимостью организации ввода, вычислений, отобра- отображения либо управления данными. До сих пор внимание акцентировалось на способах отображения данных при помощи JavaScript. Для создания хороших программ необходимо научиться также оценивать и изменять дан- данные, с которыми JavaScript-сценарии имеют дело. Ин- Инструментальные средства, реализующие подобную рабо- работу, носят название операций. Операции — суть символы и идентификаторы, ко- которые представляют способы изменения данных либо вычисления комбинаций выражений. Язык JavaScript поддерживает как бинарные, так и унарные операции. Бинарные операции работают с двумя операндами в выражении, например, 9 + х, тогда как для унарных опе- операций достаточно только одного операнда, например, Х++. Оба приведенных примера демонстрируют арифме- арифметические операции; их использование будет понятно тем, кто знаком с основами математики. Другие типы операций JavaScript оперируют со строками и логичес- логическими значениями. Они не настоль хорошо знакомы математикам старой закалки, однако их чрезвычайно Просто изучить и впоследствии предельно удобно пользоваться при работе с большими объемами текста в Internet. В этой главе детально рассматривается каж- каждый тип операций в JavaScript. ПРИМЕЧАНИЕ Netscape предлагает консольный режим работы, ко- который обеспечивает отображение результатов вычис- вычисления выражений по мере их ввода. В версиях, пред- предшествующих 4.05, данные отображались в главном окне браузера. Начиная с версии 4.05, с целью обеспече- обеспечения свободного доступа и отображения ошибок JavaScript консоль была реализована в виде отдельно- отдельного окна. Этот режим обеспечивает превосходный способ про- проверки результатов вычисления выражений. Для активи- активизации режима в поле Location наберите: javascript: Теперь можно вводить практически любую строку JavaScript, включая объявление переменных, функций и объектов, а также выражения. Пример использо- использования упомянутой возможности показан на рис. 6.1. Был выполнен ввод 12 << 1 и дважды нажата клавиша Enter. javascript typein [la « 1; . РИСУНОК 6.1. Использование КОНСОЛЫЮго режима в Netscape.
Базовое подмножество языка JavaScript Часть II Операции присваивания Рассмотрим операцию, о которой уже упоминалось ра- ранее, — операцию присваивания. Ее основная функция заключается в присваивании переменной некоторого значения, помещая таким образом это значение в па- память. Например, выражение х = 20 обеспечивает присва- присваивание переменной х значения 20. Когда JavaScript встречает операцию присваивания (=), вначале анали- анализируется правая часть с целью определения значения. После этого рассматривается левая часть — она должна представлять место для хранения значения. Если слева находится переменная, ей присваивается значение. В рассматриваемом случае х получает определенное зна- значение 20. Операция присваивания всегда выполняется справа налево, так что выражение 20 = х вызовет ошиб- ошибку в JavaScript, поскольку будет предпринята попытка присвоить 20 новое значение. Такое действие невозмож- невозможно, поскольку 20 не является переменной, но целым чис- числом, значение которого не может быть изменено. JavaScript поддерживает 11 других операций присва- присваивания, которые фактически являются комбинациями операции присваивания и арифметических или пораз- поразрядных операций. Сокращенные версии операций по- показаны ниже: Комбинации операции присваивания и арифметических операций: х += у сокращенная запись для х = х + у х -= у сокращенная запись для х = х - у х *= у сокращенная запись для х = х * у х /= у сокращенная запись для х = х / у х %= у сокращенная запись для х = х % у Комбинации операции присваивания и поразрядных операций: х «= у сокращенная запись для х = х « у х »=у сокращенная запись для х = х » у х >»= у сокращенная запись для х = х >» у х &= у сокращенная запись для х = х & у х "= у сокращенная запись для х = х ~ у х | = у сокращенная запись для х = х | у Арифметические операции При работе с числами используются арифметические операции. К основным операциям этой группы отно- относятся знак "плюс" (+), суммирующий два значения, знак "минус" (-), вычитающий одно значение из другого, звездочка (*), перемножающая два значения, а также косая черта (/), которая обозначает деление одного зна- значения на другое. Когда JavaScript встречает одну из перечисленных операций, выполняется анализ правой и левой частей выражения, имеющий целью отыскать значения, с ко- которыми предстоит работать. В примере 7+9 JavaScript воспринимает операцию плюс и просматривает обе ча- части выражения, в результате чего находится 7 и 9. Да- Далее операция плюс обеспечивает суммирование двух найденных значений и устанавливает результат выраже- выражения равным 16. Используя арифметические операции в комбинации с операцией присваивания, можно задавать новое значение переменной: х = 7 + 9 Переменная х будет теперь равна 16, и ее можно использовать снова, в том числе присваивать ей новые значения: х = х + 1 Посмотрите на два последних примера. Переменной х было присвоено какое-то значение. Затем х присваи- присваивается новое значение — текущее (в данный момент рав- равное 16) плюс 1. Увеличение значения переменной на 1 и затем при- присваивание ей же этого нового значения представляет собой достаточно стандартную операцию. Последняя настолько часто используется в компьютерных програм- программах, что некоторые языки включают специальные со- сокращенные операции, чтобы упростить запись увеличе- увеличения и уменьшения значения переменной. JavaScript - как раз относится к таким языкам. Для записи инкре- инкремента применяется ++, а для декремента — —: ++i — то же самое, что и i = i + 1 —i — то же самое, что и i = i - 1 Существует возможность использования этих сокра- сокращенных операций в префиксной и постфиксной фор- формах. Таким образом меняется порядок возврата значе- значения выражения и установки нового значения. Листинг 6.1 демонстрирует работу операций инкре- инкремента и декремента. Листинг 6.1. Пример операций инкремента и декремента. <html> <head> <title>Onepamm инкремента и декремента </title> </head> <body> <script type="text/javaScript"> var i = 0; var result = О
Операции document.write("Если i = О, "); document.write("i возвращает свое значение"); document. write (" после инкрементирования : ">; // Префиксная форма инкремента result = ++± ; document.write(result); /'/ Сбросить значение переменной i = О; document.write("<br>i++ возвращает значение -i") -¦ document.write(" перед инкрементированием : ") ; // Суффиксная форма инкремента result = i++; document.write(result); Сбросить значение переменной i = О; "<br>—i возвращает значение -i'1); " после декрементирования : ") ; // Префиксная форма декремента result = —i; document.write(result); Сбросить значение переменной i = 0; document.write("<br>i— возвращает значение -i11); document.write(" перед декрементированием : ") ; // Суффиксная форма декремента result = i—; document.write(result); ,'/ —> </script> </body> </html> После исследования кода, представленного в лис- листинге 6.1. важно понять, в какой момент увеличивает- увеличивается значение переменной i — перед или после вычисле- вычисления выражения. В первом примере переменная result получает пер- первоначальное значение i плюс 1. Во втором примере ре- результат устанавливается равным первоначальному зна- значению i до выполнения инкремента i. Два следующих примера работают аналогичным образом, однако при- применительно к операции декремента. Результаты вычислений этих четырех примеров по- показаны на рис. 6.2. Хотя это может показаться и ненуж- ненужным, рассмотренные особенности принесут несомненную ПОЛЬЗУ при записи повторяющихся частей сценария. Дан- Данная тема освещается в главе 7. Унарная операция отрицания (-) применяется в слу- случаях, когда требуется заменить положительное значение на отрицательное и наоборот. Она названа унарной, т.к. работает только с одним операндом. Если, например, Глава 6 присвоить значение переменной х (х = 5), применить к х операцию отрицания, а затем результат присвоить у '(у = -х), то значение у будет равно -5. ¦ ¦ НЯяШ^ Еспиа - 0. i возвращает свое значение поспаинкрементмроеания: 1 ++ возэращает значение I перед ^нфементироеанием: О i еозвращаетэначение i после декрементирования . Л I- вивращаетэначение! переддекрембнтмровани&м: о 'РИСУНОК 6.2. Операции инкремента и декремента из листинга б. 1. Противоположность также истинна, т.е. при отрица- отрицании отрицательного числа результат будет положитель- положительным. В обоих примерах операция отрицания не изменяет значения переменной х, которое остается равным 5. )перация взятия по модулю обозначается знаком процента (%). Найти модуль двух операндов означает найти остаток после деления первого операнда на вто- второй. В примере х = 10 % 3 переменная х получит зна- значение 1, поскольку результатом деления 10 на 3 будет 3 с остатком 1. При помощи операции взятия по моду- модулю можно легко определить, что одно число является множителем другого: при этом модуль этих двух чисел будет равен 0. Это истинно, например, для выражения х = 25 % 5. 25 разделить на 5 равно 5 без остатка, зна- значит х будет равно 0. ПРЕДУПРЕЖДЕНИЕ В ряде случаев Netscape Navigator возвращает непра- неправильные значения, когда имеет дело с дробями. На- Например, 10/3 должно вернуть 3 '/,. В окне консоли Netscape в качестве результата вычисления 10/3 ото- отображается 3.3333333333333335. Небольшая погреш- погрешность в шестнадцатом знаке после десятичной точки связана со способом, по которому дроби хранятся в памяти компьютера. Microsoft Internet Explorer реша- решает эту проблему, отображая только 14 знаков после запятой. В этом случае результатом того же вычис- вычисления будет 3.33333333333333. .. . ¦ Операции сравнения Операции сравнения используются именно для сравне- сравнения выражений. Выражения, которые используют one-
Базовое подмножество языка JavaScript Часть II рации сравнения, отвечают на вопрос, связанный с дву- двумя значениями. Ответом может быть true или false. Два знака "равно" (==) обозначают операцию равен- равенства. Использовать операцию равенства между двумя операндами — означает определить, являются ли зна- значения этих двух операндов равными. Листинг 6.2 де- демонстрирует способ отображения результатов при вы- выяснении равенства двух переменных. Листинг 6.2. Использование операции равенства. <html> <head> <title>Onepautni cpaBHem«i</title> </head> <body> <script type="text/javascript"> // Объявление переменных var x = 5; var у = 5; var z = 10; // Отображение результатов document.write ("x = " + x + "<br>") r document.write("y = " + У + "<br>"); z. = ' h Z + "<br>") ; document.write("Равны пи значения х и у w(x = у) ? ") ; document.write(x = y); ("<Ъг>Равны ли значения ¦-у и z {у = z)? ") ; document.writeln(у = z); // —> </script> </body> </html> Необходимо убедиться, что при написании програм- программы используется именно требуемая операция. Еще раз следует подчеркнуть, что операция равенства (==) про- проверяет, являются ли два значения равными, тогда как операция присваивания (=) устанавливает значение переменной. В случае использования не той операции интерпретатор JavaScript даст об этом знать. На рис. 6.3 показаны результаты выполнения кода из листинга 6.2. В табл. 6.1 приведен список всех операций сравне- сравнения. Таблица 6.1. Операции сравнения. Операция Описание Операция равенства. Возвращает true, если операнды равны между собой. != Операция неравенства. Возвращает true, если операнды не равны между собой. Операция "больше". Возвращает true, если значение левого операнда больше значения правого операнда. Операция "больше либо равно". Возвращает true, если значение левого операнда больше либо равно значения правого операнда. Операция Описание Операция "меньше". Возвращает true, если значение левого операнда меньше значения правого операнда. Операция "меньше либо равно". Возвращает 1ше,еслизначениелевогооперандаменьше либо равно значения правого операнда. П ¦ js " " ¦ i-5 z=10 ¦ счй Hi Равны пи значения х и у (х — у)? t Равш пи Энэ ениЯуи z(y— z)? SSH^fiVHWPlRfiHMi ¦ rue alse •*4 JWWWMi'iiMiwMli'iiilMMM РИСУНОК 6.З. Операция равенства излистинга 6.2. Операции сравнения обьгано используются в JavaScript для принятия решений. Они помогают выбирать путь, по которому будет следовать сценарий. Более подроб- подробно эта темя рассматривается в главе 7. ОПЕРАЦИИ СРАВНЕНИЯ В РЕАЛИЗАЦИИ JAVASCRIPT 12 В NAVIGATOR До появления JavaScript 1.1 язык был очень терпим к сравнению операндов различных типов. Например, при сравнении числа 7 со строкой " JavaScript сначала преобразовывал, или приводил, операнд строки к чис- числу и затем выполнялось сравнение. Для примера с 7 и ", операнды считались равными. В JavaScript 1.2 программист должен сначала преоб- преобразовать строку в числовую форму либо число в стро- строку. Если этого не сделать, JavaScript никогда не ска- скажет, что они равны. Листинг 6.3 показывает способ сравнения строки и числа, который возвращает одни и те же результаты для всех версий JavaScript. На рис. 6.4 приведена реакция JavaScript 1.2 на три различных сценария. Листинг 6.3 может запускаться только в браузерах, поддерживающих JavaScript 1.2, например, в Netscape Navigator 4.0-4.04. Листинг 6.3. Тестирование различных версий JavaScript. <html> <head> сравне ния</ti tl e> </head> <body> <script language="JavaScript">
Операции Глава 6 var x = "; var у = 7 ; document.write('x = ); document.write("<br>"); document.write("y = 7"); document.write ("<brXhr>">; document, write ("JavaScript 1.0 и l.KbrV) document.write("x = 3 : document.write(x = 3); document.write("<br>") ; document .write ('y = " : documen t.wri te(у = II—> </script> ¦< script language="JavaScriptl. 2 " > <! — document.write ("<brXbr>JavaScript 1.2<br>") ; a 3 : ") ; document.write (x = 3) ; document.write<"<br>"); ' : ') /" document.write (y = </script> <script language="JavaScriptl.3"> <! — document.write <"<brXbr>JavaScript 1.3 *-»и выше<Ьг>") ,' document.write("x =3 : ") ; document .write(x = 3) ; document.write("<br>"); document.write ('y = " : ' ) ; document.write (y = ") ; II—> </script> <script language="JavaScript"> document, write ("<ЬгхЬг>Универсальныи код '-•для всех версий.<br>") ; document.write ("x -0 = 3: ") ; document.write(x - 0 = 3); document.write("<br>"); " + у = " : ') ; document.write {"" + Y == ") ; II—> </script> </body> </html> Строковые операции Набор строковых операций, доступный в JavaScript, включает все операции сравнения и операцию конкате- конкатенации (+). При помощи операции конкатенации стро- строки соединяются вместе в одну длинную строку (см. листинг 6.4). Л истингб.4. Конкатенацижтрок. <html> <heac:> <title>JavaScript Unleashed»:/title> </head> <body> script type="text/javascript"> ! — / / Объявление переменных var var a = "www"; b = "company";[sr] с = " = "com"; equal to equal to ." + c; var sumOfParts; var addressl; var address2; document.write ("Part a is equal to \" '-+ a + "\".">; document.write("<br>Part b is *++ b + "\".">; document.write ("<br>Part с is *-+ с + "\".\n"); sumOf Parts = a + "." + b + addressl = "WWW.COMPANX.COM"; address2 = "www.company.com"; // Отображение результатов document, write ("<brXbr>Is sumOf Parts equal + addressl + "? ") ; document, write (sumOf Parts == addressl); document.write("<br>Is sumOfParts equal to *-»+ address2 + "? ") ; document.write (sumOf Parts == address2) ; document.write("<br>Is sumOfParts greater "-than " + addressl + "? ") ; document.write(sumOfParts > addressl); </script> </body> </html> JavaScript 1.0и 1.1 x==3 true y==" true JavaScript 1 2 x==3 false y—" false JavaScript 1 Зи выше = 3 true у == ": true Универсапьный код для всех версий, х-0 — 3 true .А. ¦на 1 ! i РИСУНОК 6.4. Сравнение строк и I чисел излистинга 6.3. Сначала сценарий выполняет инициализацию трех переменных, хранящих три части Web-адреса. Затем все три части соединяются вместе и разделяются необходи- необходимыми точками, присутствующими во всех Web-адресах. Далее выполняется проверка, содержит ли sumOfParts определенный адрес Internet. Рисунок 6.5 отражает тот факт, что JavaScript при сравнении строк учитывает регистр символов. Сравне-
Базовоеподмножествоязыка JavaScript Часть II ние выполняется слева направо, по ASCII-кодам каж- каждого символа в обеих строках. Если все коды соответ- соответствуют друг другу, строки равны. Все прописные буквы имеют коды, меньшие, чем их эквиваленты в нижнем регистре, потому и последнее сравнение в листинге 6.3 возвращает true. 3 JavaSmpt IMaashod - Microsoft Internal I Part a IS equal to *www*. Partb is equal to "со Part с is equal to *co: Is sur. equal to WWW.C0MPANY.COM? false Is sun arts equal to www с is somOJParts greater ihan'WWW. COM PAN Y.COMT But var resultMsg = (numHits 1000000) ? "Co чщиток!" : "На щите."; alert(resultMsg); При условии, что numHits равен 1000000 в любом месте программы, это выражение возвращает строку "Со щитом!"; в противном случае - "На ш те.". Вторая строка приведенного примера отображает результат для пользователя при помощи функции alert() Условное выражение может применяться для возвра- возврата данных любого типа, например, number или boolean. Следующее выражение возвращает строку или число в зависимости от значения useString: var result = useString ? "семь" : ' document.write(result); Булевы операции РИСУНОК 6.5. Результат выполнения кода из листинга 6.4. Условные операции Две операции ? и : используются для формирования ОПбОЭЦИЯ Булевы операции (также называемые логическими) используются в дополнение к выражениям, возвраща- возвращающим логические значения. Действие этих операций проще понять, изучив их использование совместно с операциями сравнения. Таблица 6.2 содержит описа- описание трех булевых операций. Приведены примеры с синтаксисом expressioni [operator] expression! и с [operator] expression. условных выражений. Эти условные операции выпол- выполняют те же действия, что и оператор if. Условное выра- выражение возвращает одно из двух значений, в зависимос- зависимости от логического значения какого-то выражения. Например, следующее условное выражение будет сообщать пользователю; что он — миллионный посети- посетитель страницы: Таблица 6.2. Булевы операции. Операция typeof возвращает тип данных, хранящихся в операнде в текущий момент времени. Это оказывается особенно полезным при выяснении, была ли определе- определена переменная. Рассмотрим следующие примеры: typeof unescape возвращает строку ""functioi typeof undefinedVariable возвращает строку "undefined". Операция Описание && Логическая операция И (конъюнкция). Возвращает true, если оба выражения expressioni и ехрге 2 имеют значения true. В противном случае возвращается false. Рассмотрим примеры: A > 0) && B > 1) возвращает true. A > 0) && B < 1) возвращает false. Логическая операция ИЛИ (дизъюнкция). Возвращает true, если хотя бы одно из значений expressioni или expression2 равно true. Если ни одно из expressioni и expression2 не равно true, возвращается false. Рассмотрим примеры: A > 0) || B < 1) возвращает true. A < 0) || B < 1) возвращает false. Логическая операция НЕ (отрицание) —унарная операция, которая возвращает противоположное значение булева выражения. Если expression равно true, возвращается false, а если expression — false, возвращается true. Эта операция не изменяет значения выражения, поскольку работает подобно арифметической операции отрицания. Рассмотрим примеры: ! A > 0) возвращает false. ! A < 0) возвращает true.
Операции' typeof 33 возвращает строку "number", typeof "A String" возвращает строку "string", typeof true возвращает строку "boolean", typeof null возвращает строку "object". ^ПРЕДУПРЕЖДЕНИЕ; /_",'¦' j * f . •, J Операция typeof была добавлена в Navigator 3.0 (JavaScript 1.1). Она будет работать только в JavaScript 1.1 и старших версиях браузеров. Определение и вызов функций Функции подробно рассматриваются в главе 8. Сейчас ознакомимся с двумя операциями, имеющими отноше- отношение к функциям. Первая — операция, которая обозна- обозначается круглыми скобками и всегда следует за именем функции. Например, функция displayName() объявля- объявляется следующим образом: function displayName () ^ [операторы] } Операция вызова функции также используется при вызове функции из любого места сценария: displayName О Круглые скобки показывают, что используется фун- функция, а не другой определенный пользователем иден- идентификатор. Вторая операция записывается символом запятой. Она используется для отделения друг от друга аргумен- аргументов функции. Аргументы всегда заключаются в круглые скобки. Функция displayName() с двумя аргументами могла бы выглядеть так: function displayName [ операторы] f (argumentl, argument2) { Операции со структурами данных Операции со структурами данных — термин, который используется при классификации двух операций, необ- необходимых для работы со структурами данных. Структу- Структуры данных — это концептуальные основы, применяе- применяемые для хранения одной или более базовых частей данных организованным способом. В JavaScript таковы- таковыми структурами являются объекты, группирующие дан- данные для конкретных целей. Операция, уже знакомая тем, кто имел дело с объек- объектами, обычно называется "точка". Обозначается она точкой (.) и носит название операцией взятия члена структуры. Она позволяет обращаться к члену (коим 1Глава 6 может быть переменная, функция или целый объект), принадлежащему определенному объекту. Синтаксис операции таков: objectName.variableName ИЛИ objectName.functionName(> ИЛИ objectName.another Ob ject Часть данных, к которой обращаются, должна стоять справа от точки. Такой способ обращения к члену струк- структуры (к переменной, функции или объекту) обычно на- называется "точечной нотацией". Операция индексирования применяется при обраще- обращении к части данных из массива. Обозначается она па- парой квадратных скобок и позволяет получить доступ к любому элементу массива. Массивы в JavaScript реали- реализованы в виде объектов (см. главу 10). Ниже показан синтаксис операции индексирования: arrayName[indexNumber] Операция индексирования предполагает использова- использование целого числа (индекса элемента массива) indexNumber. IndexNumber определяет индекс в arrayName и обеспе- обеспечивает доступ к любому члену массива. Поразрядные операции На аппаратном уровне данные хранятся в памяти пораз- поразрядно. Они записываются в двоичной системе счисле- счисления, в которой любое целое число может быть представ- представлено при помощи символов 0 и 1. В зависимости от размещения, каждый единичный разряд представляет значение 2 в степени п, где п — номер разряда, считая справа. Например, целое число 12 может быть представле- представлено двоичным кодом 1100: Для хранения большого числа, скажем 237 A1101101 в двоичном коде), потребуется 8 разрядов памяти: х 2Ъ + 1 х 26 + 1 X 27 = 237 Для хранения целочисленных значений в памяти отводится 32 разряда. В памяти число 237 фактически выглядит как 00000000000000000000000011101101, но для краткости незначащие нули не указываются. Не- Несмотря на то что целое число можно записывать в де- десятичном, восьмеричном или шестнадцатиричном виде, в памяти оно хранится в двоичной форме.
Базовое подмножество языка JavaScript Часть II Для представления отрицательных значений исполь- используется крайний слева (самый старший) разряд. Взгляни- Взгляните на следующие примеры: 10000000000000000000000000000001 = -2147483648 + 1 = -2147483647 10000000000000000000000000000011 = -2147483648 + 3 = -2147483645 11111111111111111111111111111111 = -2147483648 + 2147483647 = -1 1111111111111111111111111111111O = -2147483648 + 2147483646 = -2 Работа с двоичными представлениями целых чисел в. JavaScript обеспечивается через поразрядные операции. Самая простая из поразрядных операций — унарная опе- операция дополнения до единицы, которая обозначается тиль- тильдой (~). Она изменяет значение каждого разряда операнда на противоположное, поэтому относится к операциям отрицания. Рассмотрим, как выполняется дополнение до единицы для числа 6: X = -6 х = -00000000000000000000000000000110 х = 11111111111111111111111111111001 х = -7 Поразрядные логические операции Поразрядные логические операции рассматривают опе- операнды поразрядно. Операция выполняется над каждой парой разрядов. Например, применение поразрядной операции И к числам 01111 и 11011 дает в результате число 01011. В табл. 6.3 показан ход выполнения при- приведенного примера. Поразрядные операции сдвига Все поразрядные операции сдвига требуют двух опе- операндов. Левый операнд — это целое число, разряды ко- которого будут сдвигаться. Правый операнд задает коли- количество разрядов, на которое необходимо сдвинуть двоичное представление целого числа. Таблица 6.4 со- содержит список поразрядных операций сдвига. Таблица 6.3. Использование поразрядных логических операций. Выражение Результат 0& 1 1&1 1 &0 ¦1 &1 1 &1 а о \ о 1 1 Поразрядная операция И возвращает 1, если оба операнда равны 1 . Иначе возвращается 0. Например, 15 & 27 возвращает 11 @1111 & 11011 возвращаетОЮИ). Поразрядная операция ИЛИ возвращает 1, если хотя бы один из операндов равен 1. Иначе возвращается 0. Например, 15 | 27 возвращает 31 @1111 | 11011 возвращает 11111). Поразрядная операция ИСКЛЮЧАЮЩЕЕ ИЛИ возвращает 1, если только один из операндов равен 1. но не оба. Иначе возвращается 0. Например, 15 " 27 возвращает 20 @1111 | 11011 возвращает 10100). Таблица 6.4. Поразрядные операции сдвига. Операция Описание Операция сдвига влево возвращает целое число со сдвинутыми на несколько позиций влево разрядами. Появившиеся младшие разряды заполняются нулями. Два следующих примера демонстрируют сдвиг числа 15 влево на 1 и на 2 разряда: 15 << 1 возвращает 30 A111 « 1 возвращает 11110) 15 « 2 возвращает 60 A111 « 2 возвращает 111100) Обратите внимание, что сдвиг положительного целого числа влево на п разрядов эквивалентен умножению' этого числа п раз на 2. В большинстве случаев компьютер выполняет сдвиг влево быстрее умножения на 2. По этой причине, вместо многократного выполнения операции умножения обычно отдают предпочтение поразрядному сдвигу влево. Относительно небольшое увеличение скорости в конечном итоге приводит к существенной экономии. Применение сдвига влево к отрицательному целому числу приводит к отрицательному или положительному целому числу — в зависимости от значения старшего разряда после выполнения сдвига влево. Операция сдвига вправо с копированием знака (арифметический сдвиг вправо) возвращает значение целого числа со сдвигом его разрядов на несколько позиций вправо. Все пустые разряды заполняются копией крайнего левого (т.е. знакового) разряда. Копирование крайнего левого разряда гарантирует, что целое число останется положительным или отрицательным. Применение данной операции также представляет собой
Операции Глава 6 Операция Описание более эффективный способ деления положительного четного целого числа на 2. В случае положительного, нечетного целого числа арифметический сдвиг вправо —то же самое, что и деление п раз на 2 с отбрасыванием остатка. Рассмотрим следующие примеры: 15 » 1 возвращает 7 A111 > > 1 возвращает 0111) -15 » 1 возвращает-8A1111111111111111111111111110001 » 1 возвращает 11111111111111111111111111111000) >>> Операция сдвига вправо с заполнением нулями возвращает значение целого числа со сдвигом его разрядов на несколько позиций вправо. При этом все пустые старшие разряды заполняются нулями. Воздействие на положительные целые числа этой операции обеспечивает тот же самый результат, что и операция логического сдвига вправо. Так получается ввиду того, что копируемый знаковый разряд для положительных целых чисел — всегда нуль. Что касается отрицательных целых чисел, то операция логического сдвига вправо изменит значение старшего разряда с 1 на 0. Результат будет всегда целым числом, большим или равным 0. Рассмотрим несколько примеров: 15 >» 1 возвращает 7 A111 >» 1 возвращает 0111) -15>»1 возвращает 2147483640 A1111111111111111111111111110001 >» 1 возвращает О1111111111111111111111111111000) Зачем вообще возиться с разрядами? Поразрядные операции в большинстве сценариев не нужны. Возможно, иметь дело с разрядами вообще не придется. Однако, в некоторых случаях без такой воз- возможности не обойтись. Примером может послужить перевод числа из деся- десятичной системы счисления в шестнадцатиричную. Это потребует некоторых дополнительных усилий, т.к. JavaScript позволяет отображать только десятичные представления чисел, хранящихся в памяти. Встроенные способы отображения чисел в других системах счисле- счисления отсутствуют. Используя поразрядные операции, преодолеть упомянутое препятствие относительно про- просто. Например, переменная х хранится в памяти в дво- двоичном коде. Показанный ниже код обеспечивает вывод значения переменной х в десятичном представлении (т.е. 220): var х = OxDC; // Отображение числа 220 document.writeln(x); В JavaScript не существует какого-либо способа ото- отображения 220 в шестнадцатиричном формате (т.е. DC). Функция подобного рода оказалась бы весьма полезной при оперировании с кодами цветов HTML, которые за- записываются в шестнадцатиричной системе. Самый про- простой способ получить шестнадцатиричное число — взять двоичный код целого числа и перевести его в шестнад- шестнадцатиричный. Точно также шестнадцатиричные коды достаточно просто переводятся в двоичные. Четыре разряда памяти могут определять 16 различ- различных значений. Поскольку для записи шестнадцатирич- шестнадцатиричных кодов применяются 16 цифр, для хранения каждой шестнадцатиричной цифры требуется как раз 4 разря- разряда. В 32-разрядном целом числе 4 младших разряда па- памяти представляют цифру младшего разряда шестнад- шестнадцатиричного целого числа. Следующие 4 разряда хра- хранят следующую цифру и т.д. Для того чтобы прочитать только 4 разряда, исполь- используется операция & и управляющее значение. Управля- Управляющее значение должно хранить 1 в каждом разряде, соответствующем читаемому разряду целого числа. По- Поскольку требуется значение первых 4 разрядов, управ- управляющее значение должно содержать 1 в первых четырех разрядах. Все другие разряды должны содержать 0. Для чтения младших четырех разрядов управляющее значе- значение должно быть равно 1111 A5 или OxF): Управляющее значение: 00000000000000000000000000001111 & Преобразуемое целое: 00000000000000000000000011011100 = Результат: 00000000000000000000000000001100 Результат — это копия первых 4 разрядов преобра- преобразовываемого целого числа. Сравните его с каждой из 16 шестнадцатиричных цифр и убедитесь, что оно равно С. Чтобы найти следующую шестнадцатеричную циф- цифру, необходимо скопировать следующих 4 разряда это- этого целого числа. Это лучше всего сделать путем сдвига всех разрядов целого числа на 4 позиции вправо и за- затем воспользоваться тем же управляющим значением: Управляющее значение: 00000000000000000000000000001111 & Преобразуемое целое: 00000000000000000000000000001101 = Результат: 00000000000000000000000000001101
Базовое подмножество языка JavaScript Часть II Результат соответствует цифре D. Листинг 6.5 демонстрирует рассмотренный алгоритм целиком. Используя только операции, упомянутые ра- ранее, можно преобразовать любое 8-разрядное число в строковое представление его шестнадцатиричного экви- эквивалента. Для этого сначала надо присвоить переменной intValue преобразуемое значение. Затем отобразить зна- значение, дабы подчеркнуть тот факт, что JavaScript ото- отображает только десятичное значение DC, т.е. 220. Да- Далее выполняется перевод двоичной формы числа 220 в шестнадцатиричную и отображение результата (см. рис. 6.6). Листинг 6.5. Преобразование десятичного числа в шестнадцатиричное с использованием поразрядных операций. <html> <head> <title>npeo6pasoBaj»re десятичного числа в шестнадц.атиричное</^Ы.е> </head> <body> <script type="text/javascript"> // Объявление переменных var originallnt; // intValue хранит любое 8-разрядное число var intValue = OxDC; var controlvalue = OxF; var fourBitValue; var hexChar = "" ; var hexString = ""; document.writeln("При отображении целых чисел, хранящихся в памяти,") document.writeln("JavaScript использует их десятичные ") ; document.writeln("эквиваленты: " + intValue); originallnt = intValue; fourBitValue hexChar = hexChar ~ hexChar = hexChar = hexChar ™ hexChar = hexChar ¦ hexChar = hexChar ~ hexChar ¦ hexChar = hexChar = hexChar = hexChar = hexChar ¦ hexChar = controlValue (fourBitValue =¦= (fourBitValue ¦= (fourBitValue = (fourBitValue = (fourBitValue =¦ (fourBitValue == (fourBitValue ш* (fourBitValue = (fourBitValue = (fourBitValue "¦ (fourBitValue = (fourBitValue ¦= (fourBi tValue = (fourBitValue = (fourBitValue =¦ (fourBitValue =™ ? 0x0) Oxl) 0x2) 0x3) 0x4) 0x5) 0x6) 0x7) 0x8) 0x9) QxA) QxB) QxC) OxD) OxE) QxF) intValue •p HI Q it ? " i " 1 " ? " ?' " ? 6 ? '" , „8,i ¦p "9" T' '"A" ,, ..Bi. ? '"C" 1 "D" •3 "E" ? "F" hexChar: hexChar; hexChar; hexChar; hexChar, hexChar, hexChar; hexChar; hexChar; hexChar; hexChar, hexChar; hexChar; hexChar; hexChar; hexChar; // Построить hexString, помещая в нее пифры справа налево hexString = hexChar + hexString; // Сдвинуть intValue на 4 разряда вправо intValue = intValue » 4; // Получить значение следующих 4 разрядов fourBitValue = controlValue ? intValue; // Отыскать соответствующую шестнадцатиричную цифру // и присвоить ее строке nexChar hexChar hexChar hexChar lexChar nexChar lexChar lexChar lexChar lexChar hexChar — (fourBitValue • = (fourBitValue = )вый эквивалент ¦¦ 0x0) = Oxl) = i (fourBitValue = 0x2) = (fourBitValue ¦ ¦= 0x3) = (fourBitValue ¦« 0x4) = <f ourBi tValue = = i (fourBi tValue = s» (fourBitValue ¦ ¦ (fourBitValue = •= '(fourBitValue * ™ (fourBitValue = = '0x5) = 0x6) = 0x7) = 0x8) ¦= 0x9) = OxA) ¦5 ? ¦p •¦i f •p 1 " " " »3.. " „5„ 6 " "8" и gii "A" hexChar hexChar hexChar hexChar hexChar hexChar hexChar hexChar hexChar hexChar hexChar hexChar
Операции Глава б Y hexChar = hexChar = hexChar = hexChar = hexChar = hexString (f ourBitValue = (fourBitValue = (fourBitValue = • (fourBitValue = (fourBitValue = OxB) OxC) OxD) OxE) OxB) = hexChar + hexString; ? ? ? ¦a ¦y "B" »C" "D" "E" "P" : hexChar; : hexChar; : hexChar; : hexChar; : hexChar; document .write ("<br>lr + originallnt 4- ' отображается в"); document.write(" в шестнадцатиричной формате: document.writeln(hexString); // конец сокрытия —> </script> < /body > </html> При аж 220 в памяти. JavaScript • ¦¦¦формате: > тихдесятичныеэ РИСУНОК б.б. Преобразование десятичного числа в шестнадцатиричное. ПРИМЕЧАНИЕ ' В к( предыдущего примера при поиске соответствия многократно используются условные выражения. Бо- Более эффективный способ сравнения ряда чисел связан с организацией циклов (см. главу 7). При исследовании предыдущего примера обратите внимание на то, сколько нулевых разрядов остались неиспользованными при хранении относительно не- небольшого числа. Это — еще одна область, в которой поразрядные операции оказываются полезными. При помощи поразрядных операций можно сэкономить па- память, сохраняя данные в неиспользуемой части любой переменной. Например, если сценарий работает с большой груп- группой положительных целых чисел, не кревышающих 255, то в одном 32-разрядном слове поместятся четыре та- таких числа. Используя простую поразрядную операцию, можно извлекать любое из этих чисел. Стоит отметить, что с такими объемами ОЗУ, которые имеют на сегод- сегодняшний день большинство компьютеров, экономия про- пространства обычно не стоит затраченных на его добыва- добывание усилий. С другой стороны, поскольку JavaScript IH для выполнения на различных платформах, нельзя знать заранее, кто будет выполнять сценарий, — у кого-то ведь может и не хватить памяти. Но даже при- принимая во внимание сказанное, волноваться по поводу нехватки памяти нужно начинать только, когда в памяти хранится достаточно много данных. Приоритеты выполнения операций При создании выражений, которые включают более одной операции, необходимо помнить, что JavaScript не обязательно вычисляет выражение справа налево или наоборот. Каждая часть выражения вычисляется в по- порядке, основанном на приоритете каждой операции. Рассмотрим такой пример: х = а * ь + с а умножается на 1). после чего полученный результат прибавляется к с. Наконец, результат сложения присва- присваивается х. Операция умножения обладает более высо- высоким приоритетом, нежели операция сложения, поэто- поэтому умножение выполняется первым. Если вначале необходимо выполнить сложение, выражение заключа- заключают в круглые скобки: х = а * (Ь + с) Круглые скобки — это операция, которая увеличи- увеличивает приоритет заключенного в них выражения. Одно- Однотипные операции вычисляются слева направо. В табл. 6.5 перечислены операции в порядке их при- приоритетов — начиная с самого низкого и до самого вы- высокого.. Таблица 6.5. Приоритеты операций. Название операции Операция Запятая Присваивание Условие Логическое ИЛИ Логическое И Поразрядное ИЛИ Поразрядное ИСКЛЮЧАЮЩЕЕ »= >»= &= 3= «=
Базовое подмножество языка JavaScript Часть II Название операции Операция Поразрядное И Равенство Сравнение Поразрядный сдвиг Сложение/вычитание Умножение/деление Отрицание/приращение Вызов/структурирование данных 8, < « + * ! 0 5= <= > >= : » >» - / % D ¦ Один из эффектов, связанных с приоритетами опе- операций, заключается в определении типа данных резуль- результата выражения. Это станет очевидным при попытке конкатенации строк и Я (см. листинг 6.6). Листинг 6.6. Приоритеты операций и типы данных. <html> <head> <ЫЪ1е>Приоритеты onepaiwit</title> </head> <body> <script type=" text/ javascript "> <!-- var carLength = 2 + 3; document.write(carLength); carLength = "<br>" + 2 + 3-1 document.write(carLength); carLength = "<Ьг>Длина в метрах: "' + 2 + 3; document.write(carLength); carLength = "<Ьг>Длина в метрах: " + B + 3) ; document.writeln(carLength); //--> </script> </body> </html> Операции с одинаковыми приоритетами вычисляют- вычисляются слева направо. Операция сложения обладает таким же приоритетом, что и операция конкатенации, поэто- поэтому JavaScript будет выполнять все сложения и конкате- конкатенации слева направо. Обратите внимание на показанное на рис. 6.7 резуль- результирующее окно. Два первых примера работают, как и следовало ожидать. Третий пример показывает, что мо- может получиться, когда JavaScript по-своему учтет при- приоритеты. Первый знак + преобразует число 2 в строку и добавляет ее в конец "Длина в метрах: ". В результа- результате получается строка "Длина в метрах: 2". Потом то же самое происходит с числом 3 и получается "Длина в метрах: 23". Однако, если вместо этого требуется ото- отобразить сумму 2 и 3, следует использовать круглые скоб- скобки, тем самым увеличив приоритет 2 + 3. В этом слу- случае оба операнда — числа, и JavaScript выполнит сложение раньше конкатенации (см. рис. 6.7). Резюме и присваивания устанавливают значения пере- переменных. Наряду с простой, JavaScript поддерживает 11 дополнительных операции присваивания, которые на самом деле являются комбинациями арифметических или поразрядных операций с простой О] цией при- присваивания. " .^1.У1'1ь№ЩЩЩ$&Щу?Е™Я1:'ШЯ] ^ 23 метр] Длина в метр; Длина в метрах- 5 Л\ *•! ¦ ¦ • > РИСУНОК 6.7. Приоритетыопераций и типы данных. Арифметические операции позволяют выполнять базовые математические операции в JavaScript. Сюда входят операции сложения, вычитания, умножения, де- деления и вычисления по модулю. JavaScript также вклю- включает операции инкремента и декремента — для корот- короткой записи двух наиболее частых математических операций. Математические операции более высокого уровня также встроены в JavaScript, но к ним следует обращаться через объект Math. Операции сравнения сравнивают два значения и возвращают true или false. С их помощью выясняется, равно ли одно значение другому, больше или меньше другого, а так же и любые комбинации этих вопросов. Условные операции позволяют воз ~ь одно из двух значений выражений, которые могут содержать любой тип данных. Возвращаемое значение зависит от значения определенного логического выражения. Строковые операции включают в себя операцию конкатенации и все операции сравнения. Операция конкатенации используется для связывания двух строк вместе с целью формирования новой строки. Операции сравнения могут использоваться со строками для срав- сравнения их ASCII-значений. Начиная с крайнего левого символа строки, каждая пара символов сравнивается друг с другом. Возвращается true или false. Булевы операции используются в логических выра- выражениях. Операция И возвращает true, если оба ее опе- операнда — true, а иначе — false. Операция ИЛИ возвра- возвращает true, если по крайней мере один из ее операндов равен true. Иначе она возвращает false. Операция НЕ возвращает true, если ее операнд false, и false, если опе- операнд — true. Операция typeof появилась в JavaScript 1 и пред- представляет собой встроенную операцию, возвр
Операции строку, которая представляет тип данных операнда. Это особенно полезно при выяснении, была ли переменная определена. Две операции работают с объявлением и использо- использованием функций JavaScript. Операция вызова функции (круглые скобки) всегда следует за именем функции и заключает в себе список аргументов, которые может принять функция. Операция "запятая" используется для отделения аргументов друг от друга. Для работы с массивами и другими объектами необ- необходимы еще две операции. "Точкой" обычно обознача- обозначают доступ к элементу объекта. Это — стандартная точечная нотация. Операция индексирования исполь- используется для индексации элементов массива. Она содер- содержит имя массива и целое число, обозначающее распо- расположение элемента, к которому обращаются. JavaScript дает доступ к двоичному представлению любого целого числа с помощью поразрядных операций. Глава 6 Поразрядная операция дополнения используется для изменения значения каждого разряда целого числа на противоположное. Поразрядные логические операции применяются для сравнения двух целых чисел. Двоич- Двоичная форма операнда используется для работы с каждой парой разрядов в числах. Логическая операция выпол- выполняется над каждой парой разрядов и возвращается це- целое число. Поразрядные операции сдвига сдвигают раз- разряды целого числа вправо или влево на п позиций. При сдвиге вправо JavaScript позволяет выполнить арифме- арифметический или логический сдвиг. Когда все операции в выражении имеют равные при- приоритеты, JavaScript вычисляет выражение справа нале- налево. Если же приоритет операций разный, то сначала выполняется операция с самым высоким приоритетом, затем следующая по приоритету и т.д. В JavaScript каж- каждая операция обладает совершенно определенным при- приоритетом.
Управляющие структуры и организация циклов В ЭТОЙ ГЛАВЕ Условные операторы ¦Операторы организации циклов Метки Оператор with Оператор switch Проектирование сценариев, предполагающих приня- принятие решений во время выполнения, — наиболее интерес- интересная часть JavaScript. В сценарии, где требуется прини- принимать решения на основе его текущего состояния, просто обеспечивают вывод вопроса и затем, в зависимости от ответа, выбирают путь. Рассмотрим для примера планирование утра моего рабочего дня. Мне доступны несколько различных ва- вариантов, из которых на основе определенных факторов я выбираю один. Я редко готовлю еду, посему наиболее важный вопрос, который я задаю себе каждое утро, — не голоден ли я. Если да, я выбираю маршрут, проходящий через продуктовый магазин. К моменту завершения упа- упаковки собственного завтрака я, как правило, уже немно- немного опаздываю. Дабы восполнить потерянное время, я двигаюсь по направлению к скоростному шоссе, где могу увеличить скорость. С другой стороны, если я не голо- голоден (что случается весьма редко), то миную продукто- продуктовый магазин и еду на работу со скоростью на 10 миль в час медленнее. Используя подобного рода планирование, можно со- создавать и программы на JavaScript, выполняющие раз- различные операции в зависимости от текущего состояния. Например, в главе 6 рассматривалось, как проверить, яв- является ли переменная равной какому-то значению или даже ряду значений. С использованием управляющих структур появляется возможность заставить программу выбирать различные пути в зависимости от результата упомянутой проверки. Итак, имеем первую тему, кото- которой посвящена данная глава. Поскольку размеры программ неуклонно возрастают, неплохо было бы учесть немаловажный фактор — сколь- сколько времени потребуется клиенту для их загрузки. Луч- Лучший способ сэкономить на количестве исходного текста в сценарии предусматривает применение операторов цикла. Прибегнув к помощи циклов, можно достигнуть ситуации, когда всего лишь несколько строк программы обеспечивают выполнение большого количества одно- однотипных операций. Это поможет сократить размер сце- сценариев и избежать многократного набора одних и тех же команд. Помимо прочего, в главе демонстрируются спо- способы повышения эффективности сценариев. Условные операторы В главе 6 рассматривалась операция ?:. Эта операция используется для создания двухшагового процесса. Сна- Сначала выражение оценивается на предмет равенства true или false. Далее, в зависимости от результата, возвраща- возвращается одно из двух значений. Если выражение true, воз- возвращается первое значение, а если — false — второе. Встречаются сценарии, принимающие решение в за- зависимости от значения выражения, использующего опе- операторы if и else. Однако результат будет другим. Вместо возвращения зависящего от результата значения, про- программа выбирает один из двух путей выполнения. Так, можно заставить JavaScript выполнять множество раз- различных функций, зависящих от любой доступной ин- информации. if Оператор if относится к числу наиболее популярных. Каждый язык программирования содержит его в той или иной форме, и его использования избежать, как прави- правило, не удается. Оператор if применяется следующим об- образом: if (условие) { [ оператора]
Управляющие структуры и организация циклов Глава 7 В качестве условия может указываться любое логи- логическое выражение. Если результат условия равен true, выполняются операторы, посему работа программы про- продолжается. Если условие возвращает false, операторы иг- игнорируются и работа продолжается. В листинге 7.1 приводится сценарий, который от- отдел маркетинга мог бы предложить разместить на Web- сайте компании. Сценарий начинается с установки visitorlnterest в одно из двух значений. В данном примере выбирается "Technical Support" (то бишь, техническая поддержка) и комментируются альтернативные варианты. Сценарий доходит до первого оператора if, который проверяет, равно ли значение visitorlnterest строке "New Products" (т.е. новый продукт). Последнее вычисленное значение этого выражения — false, поэтому блок опера- операторов после if игнорируется. Затем сценарий доходит до второго оператора if и сравнивает значение visitorlnterest со строкой "Technical Support". Выражение возвращает true, что приводит к выполнению кода, заключенного в фигурные скобки. Независимо от того, чему равно значение visitorlnterest, последний оператор всегда выполняется, поэтому про- продавец Виктор Франкенштейн делает шаг к посетите- посетителю. Результирующий вывод показан на рис. 7.1. Если visitorlnterest присвоить какое-то другое значение, ре- результат изменится. Обычно набор операторов заключается в фигурные скобки. Это придает сценарию логический вид и ока- оказывается особенно полезным в случае вложенных опе- ЛИСТИНГ 7.1. Использование оператора if для принятия раторов if (т.е. при использовании одного оператора if внутри другого). меня зовут Виктор вначале позвольте познакомить вас | Наша нов.эя продукция удовлетвори Сейчас доступна и техническая пОДД&ржкз з новой продукцией все ваши потребности! РИСУНОК 7.1. Виктор Франкенштейн делает шаг навстречу посетителю. Листинг 7.2 демонстрирует использование логичес- логических переменных для выбора пути, по которому пойдет сценарий. Первый оператор if оценивает переменную needslnfo. В данном случае needslnfo имела значение true, так что JavaScript выбирает первый блок if и про- продолжает работу в нем, т.е. выводит на экран "Наши продукты использует весь мир.". Далее очередь дохо- доходит до второго (вложенного) блока if, и оценивается needsMorelnfo. решения. <html> <head> е решений при помощи оператора if</title> </head> <body> <script type="text/javascript"> <! — ' Объявление переменных var visitorlnterest; .// visitorlnterest = "New Products"; visitorlnterest я "Technical Support"; document.writeln("Привет, меня зовут Виктор Франкенштейн!"); // Оценка значения visitorlnterest if (visitorlnterest "New Products") { document. writeln ("Спасибо интерес, проявленный к нашим товарам! "); if (visitorlnterest = "Technical Support") { йчас доступна и техническая поддержка. ") ; document.writeln("Однако вначале позвольте познакомить вас document.writeln("с новой продукцией!"); document, writeln (<br>"Hama новая продукция удовлетворит все ваши") document.writeln("noTpe6HOCTH!"); // —> </script> </bcdy> </html>
Базовое подмножество языка JavaScript Часть II Листинг 7.2. Вложенные операторы if. <html> <head> <title>npiiHHTOie решений при < лот оператора if</title> </head> <body> <script type="text/javascript"> <! — II Об-ьявление переменных var needsInfo,- var needsMorelnf о ,¦ // Если установить одну из приведенных ниже переменных в false- вывод изменится. needslnfo = true; needsMorelnfо = true; document, write In ("Я работаю на Лучшие Продукты Интернешинл! ") ; if (needslnfo) { document.writeln("Наши продукты использует весь мир."); if(needsMorelnfo){ document.writeln ("<Ьг>Япросто не могу понять, как же вы могли") ; document.writeln("обходиться без них."); ) document.writeln ("Самый простой способ заказать наши продукты — воспользоваться ^онлайновым магазином."); // </script> </body> </btml> Опять-таки, возвращенное значение — true, поэто- поэтому операторы внутри второго блока будут выполнять- выполняться. После завершения вложенного блока if JavaScript вы- выполняет все оставшиеся инструкции первого блока. Обратите внимание, как фигурные скобки помогают от- отличать отдельные блоки программы друг от друга. Из рис. 7.2 видно, что строки программы выполнялись в порядке их написания. Изменяя значения needslnfo и needsMorelnfo, можно получить три различных резуль- результата. Помните, что если needslnfo присвоить значение false, программа не сможет перейти ко второму блоку if. В этом случае значение needsMorelnfo роли не играет, поскольку оцениваться оно не будет. Извините, Виктор, но если посетителю вообще не нужна информация, ему уж точно не нужна дополнительная информация. Я 1Таю на Лучшие Продукты I Наши продукты испольэу«Т| :G0 всем мире Я просто не могумонять, как : г. могли Самый простой способЗЭХЗЭь наши продукты - BOci тэться онлайновым if ..else Иногда одной конструкции if оказывается недостаточ- недостаточно. Зачастую требуется также зарезервировать набор операторов, которые будут выполняться в случае, ког- когда условное выражение возвращает false. Это можно сде- сделать, добавив еще один блок непосредственно после блока if: if i (условие) операторы else { операторы Кроме т >, имеется возможность скомбинировать часть else с другим оператором if. Использование тако- такого метода позволяет оценить несколько разных возмож- возможных сценариев перед выполнением нужной операции. Изящество данного метода состоит в том, что в конце можно определить тот же сегментом else. Формат упо- упомянутого типа оператора выглядит так: if (условие) С оператора } else if (условие) { операторы ) else { операторы > Что может быть хуже придирчивого компьютера? Листинг 7.3 демонстрирует, как можно создать интер- РИСУНОК 7.2. Один I трех возможных результатов.
Управляющие структуры и организация циклов Глава 7 активную Web-страницу с помощью всего лишь не- нескольких строк кода. Здесь жестко задано значение клю- ключа purchaseAmount, которое определяет ход сценария. Для настоящего взаимодействования сценария с пользо- пользователями потребуется обеспечить возможность пользо- пользовательского ввода. В таком случае purchaseAmount мо- может принимать любые значения, в зависимости от желания заказчика. Это делается с помощью JavaScript и стандартных входных HTML-объектов, таких как пе- переключатели и текстовые объекты. В главе 17 эта про- проблема обсуждается более подробно. В рассматриваемом примере клиент не соизволил по- потратить достаточную сумму, дабы удовлетворить Викто- Виктора Франкенштейна. Условный оператор получает значе- значение false, и программа переходит на блок else. Посмотрев на рис. 7.3, можно воочию убедиться, как настойчивый продавец "разогревает" потенциального клиента. Листинг 7.3. Блок else, соответствующий значению false. <htmi> <head> <title>npra«roie решений при помощи оператора if </title> </head> <body> <script type="text/javascript"> <> — // Объявление переменных var purchaseAmount; purchaseAmount = 10.00; if {purchaseAmount > 500. 00) { document, writeln ( "Спасибо за покупку!") ; }else{ document.writeln ( "Спасибо, однако я '¦•уверен, что у меня есть " > ; document, writeln ("еще кое-что, от чего *¦*вы не сможете отказаться. ") ; </script> </body> </html> try..catch Оператор try. .catch используется для замены заданного по умолчанию способа обработки ошибок. Эта тема в главе подробно не рассматривается. Операторы организации циклов Организация цикла внутри сценария преследует широ- широкий спектр целей. Рассмотрим одно простое, но весьма распространенное применение цикла. Например, напи- написание программы, отображающей числа от 0 до 9, — на первый взгляд, быстрая и простая задача. Просто запи- записываются 10 команд для отображения каждого числа: document.writeln document.writeln ¦("О"); ("l"); document.writeln ("9"); Это легко сделать для чисел от 0 до 9, но что если потребуется сосчитать до 1000? Можно последовать тому же способу, но тогда программа потребует гораздо боль- больше времени на написание и загрузку в браузер. Наилуч- Наилучший способ счета до 1000 или любого другого числа зак- заключается в использовании той же самой команды отображения, но с переменной вместо литерала. В дан- данном случае потребуется обеспечить только одну вещь — инкрементировать переменную и повторять команду отображения. JavaScript располагает соответствующими инструментами. for Оператор for используется для организации цикла в сце- сценарии. Перед детальным изучением оператора for на основе листинга 7.4, рассмотрим его обобщенный син- синтаксис: for ([выраженяе_инициалиэации] ; "* [ выражение_условия] ; [выраженг*е_цикла] ) ( операторы ) Три выражения, заключенные в квадратные скобки, не являются обязательными, тем не менее, если даже уб- убрать одно из них, точка с запятой все же потребуется. Именно точка с запятой обеспечивает должное место для каждого выражения. Выражение инициализации обычно применяется в целях инициализации переменной и даже объявления, что конкретная переменная является счетчиком цикла. Выражение условия должно иметь значение true перед каждым выполнением операторов, заключенных в фи- фигурные скобки. Наконец, выражение цикла, как прави- правило, инкрементирует или декрементирует значение пере- переменной, которая используется в качестве счетчика цикла. РИСУНОК 7.3. Один и. двух возможных результатов.
Базовое подмножество языка JavaScript Часть II Листинг 7.4 демонстрирует использование опера- оператора for для организации счета от 0 до 99 с отображе- отображением каждого числа. Для того чтобы уместить резуль- результат на стандартной странице, после каждых 10 чисел выводится символ новой строки (см. рис. 7.4). Листинг 7.4. Использование цикла for для счета от О до 99. <html> <head> <title>Uraui счета от 0 до 99</title> <body> <script type="text/javascript"> < ! // Вывести заг( ювочную часть iocument. write ("Числа от 0 до 9 document.write ( '<hr size=" width=0%" for (var i = 0; i < 100; ++i) { // Символ новой строки после каждого // 10-го числа if(i%10 = 0) { document.write( '«сЬгУ ) ; // Вывести собственно тта document, write (i + ","); // Последнее число, следовательно, //завершаемся. . . ("<ЬгхЬг>После завершения i равно : + i) </script> </body> </html> . ;: ..Ssrt R№H H in StM юла от 0 до 90 ! 0.1.2.3.1.5.6,7.8,9. .12 13 14 15 JO .21.22.23.2-1.25.26.27,23.29. 30,31.32.33,34,35.36,37.38,39. 40.41.42.43 44.45.46.47,48,49, 50.51.52.53.54.55.56.57.58.59, 60.61.62.63,64 65 66.67,68.99 70.71.72.73.74.75.76.77.78.79. 90,91,92,93,^4,95,96 .У7.98,99. ння цикла i равно 1С . : '3i ¦ • UfJ' '¦•- J. e''"'.~PmA'~' . ¦:$" . ?¦ РИСУНОК 7.4. Результат 100-кратного выполнения цикла. В листинге 7.4 порядок выполнения операторов выг- выглядит так: выражение инициализации объявляет пере- переменную i и устанавливает ее значение равным 0. Затем переменная i проверяется на предмет, меньше ли она 100. Когда i все еще равна 0, выражение условия возвра- возвращает true и программа выполняет операторь; в фигур- фигурных скобках. Как только программа выполнит все опе- операторы и достигнет закрывающей фигурной скобки, она вычисляет выражение цикла ++L При этом i увеличи- увеличивается на 1 и, таким образом, выполнение первого пол- полного цикла завершается. Процесс начинается сначала. На сей раз JavaScript знает, что выполнять раздел инициализации для цикла уже не требуется. Выражение условия вычисляется сно- снова. Если i все еще меньше 100, выполняется второй цикл. Выполнение набора операторов внутри блока for продол- продолжается до тех пор, пока i не достигнет 31 .1 100. И в 99-й раз условное выражение возвращает tru программа выполняется в последний раз. Значение i уве- увеличивается еще раз и становится равным 100. Вычисле- Вычисление условного выражения дает в результате false, поэтому выполнение цикла прерывается. Управление переходит к операторам, следующим непосредственно за закрыва- закрывающей фигурной скобкой. Поскольку значение i было увеличено до 100 до за- завершения цикла, 100 и представляет собой последнее значение i. Обратите внимание, что в соответствие с пра- правилами, рассмотренными в главе 5, i можно I вать вне цикла. ПРИМЕЧАНИЕ Если условное выражение возвращает false при пер- первом проходе цикла, код в фигурных скобках выпол- выполняться не Тэудет. . Подобно операторам if, циклы for также могут быть вложенными. Листинг 7.5 содержит код прохода по каж- каждой координате сетки 10x10. Для каждой итерации пер- первого цикла имеют место 10 итераций вложенного цик- цикла. В результате вложенный цикл будет выполняться 100 раз. Л истинг7.5. Пример вложенного цикла. <htinl> <head> <ti ие>Влохенные </head> <body> <script type="text/javascript"> ent.write("Все координаты х,у @,0) и (9,9) :<br>"); for (var x = 0; x < 10; ++x) { for (var у = 0; у < 10; ++y) { document.write("("+x+","+У+"),"); } document.write('<br>'); 1 "<Ьг>После завершения цикла х равно : + х) nent. write ("< >г>После завершения '¦>цикла у равно : + у) ;
Управляющие структуры и организация циклов и --> </script> </body> </html> Переменной х сначала присваивается значение 0. Затем JavaScript доходит до вложенного цикла и присва- присваивает переменной у также значение 0. Вложенный цикл отображает значения х и у и затем увеличивает у на 1. Вложенный цикл продолжается до тех пор, пока у не станет равным 10. В этот момент уже сгенерировано 10 наборов координат. Выполнение вложенного цикла пре- прерывается и управление возвращаются ко внешнему цик- циклу. Значение х увеличивается на 1, после чего вновь за- запускается вложенный цикл. JavaScript знает, что вложенный цикл необходимо начать с самого начала, в связи с чем выражение ини- инициализации должно вычисляться повторно. Таким обра- образом, у присваивается значение 0 и операторы выполня- выполняются еще 10 раз. Процесс продолжается до тех пор, пока х не станет равным 10 и выполнение внешнего цикла, наконеи, завершается. В результате отображается 100 на- наборов координат (см. рис.7.5). m ¦ * *^& Все «оопджаты и.у между @.0) и (Э.Э) B.0|,B.1).B 2].B3|,B,<1)]B15).B.6),B,7IB.е),B,ЭI Eтя'.пв'ак5яа№!41'в!я.(вяя!п№!»!в[иГ После завершения циияа х paБ^ После зав шения цикла у рав 1^—ЧГ7|| ^... :,»tv ;i- г;3 РИСУНОК 7.5. 100пар координат, сгенерированных в двух циклах. Поскольку каких-либо ограничений на количество вложенных циклов нет, следовательно, число координат можно увеличить до трех или, скажем, до четырех. Дан- Данный метод можно использовать для обращения к элемен- элементам многомерного массива. for..in Для использования цикла for..in потребуются знания ¦объектов JavaScript, исчерпывающая информация о ко- которых может быть найдена в главе 9. Конструкция for.an предоставляет возможность вы- выполнения набора операторов для каждого свойства объекта. Цикл for..in можно использовать с любым Глава 7 объектом JavaScript, независимо от его свойств. Если объект не имеет свойств, цикл не выполняется. Цикл for..in работает также и с пользовательскими объекта- объектами. Переменная пользовательского объекта JavaScript рассматривается как свойство, и поэтому для каждой из них выполняется цикл. Синтаксис выглядит так: for ( свойств операторы I in объект) Тут свойство — это строковый литерал, сгенериро- сгенерированный JavaScript. При каждом проходе цикла свойству присваивается имя следующего свойства, содержащееся в объекте, и так до тех пор, пока не переберутся все свой- свойства. В листинге 7.6 такая функциональность применя- применяется для отображения имен и значений всех свойств объекта Document (см. рис. 7.6). . t -I =, V Г; '. * * *Ф-Чссгп Ь- > и;. * -¦¦'- |ГУГ^1-1>-Л.1-».._Т< :-texts/7- Q.html location - Н ¦ .'I'l/tiooksfjscnpt/pk forms - [object FormArrayl II links - [object LinkArray] [object ^ncnorAiray] I applets [object AppletArray] eHs = [object EmbedArray] I images - title Использование цикпа(ог .^ - свойств объекта document URL = fi || referrer = lastModifietl - Friday. October !:¦ j"'" ¦ 17:50 35 cookie = domain = bgColor = #fffW IgColor - ЙО00000 HinkColor=#OOOOee ktrtkColor=#55fa8b alinkColor=#tfOOOO yjidjh ^ 598 .¦¦¦¦ . РИСУНОК 7.6. Список свойств объекта Document вместе с их значениями. ПРЕДУПРЕЖДЕНИЕ Цикл for..in работает только в версии JavaScript 1.1 и выше. Не следует забывать, что этот цикл не отлича- отличается корректной работой в Microsoft Internet Explorer 3.0 (JScript 1.0). Листинг 7.6. Использование цикла for..in. <html> <head> <title>JavaScript Unleashed</title> </head> <body> <script language="JavaScriptl.1" type="text/javascript"> < I // * переменных var anObject = document; var propertylnfo = for (var propertyName in anObject) { propertylnfo = propertyName + ' — + anObject[propertyName] ; document.write(propertylnfo + "<br>");
Базовое подмножество языка JavaScript Часть II </script> </body> </html> while Оператор while действует подобно циклу for, однако не включаетвсебяфункцииинициализациииприращения переменных во время их объявления. Переменные необходимо объявлять заранее, а инк- инкремент или декремент их определять в рамках блока операторов. Рассмотрим синтаксис while: while (выралсенив_условия) { операторы Листинг 7.7 предоставляет пример использования ло- гическойпеременнойвкачестве флажка, определяющего продолжениевыполнения цикла. Этапеременная, status, объявленадо начала цикла и ей присвоено значение true. Как только i станет равно 10, status получит значение false, после чего цикл завершается. Результат листинга 7.7, как показано на рис. 7.7, — это сумма целых чисел от 0 до 10. Листинг 7.7. Использование цикла while. <html> <head> <title>JavaScript Unleashecl</title> </head> <body> <script type="text/javascript"> / / Объявление переменных var i = 0; var result = С var status = true; document.write(") ,- while(status){ result += Л document.write(" + " + i) if (i = 1 )) { status = false; document.writeln(" 11 + result) , </script> < /body> </html> dcwhile Начиная с JavaScript 1.2, предлагается конструкция do..while. Она работает подобно оператору while за ис- исключением того, что условное выражение не проверя- проверяется вплоть до завершения первой итерации. Этот спо- способ гарантирует, что набор операторов, здящихся в пределах фигурных скобок, будет выполнен по крайней мере один раз. РИСУНОК 7.7. Результат выполнения листинге 7.7 — одиннадцать итераций цикла while. Листинг 7.8 содержит пример, в котором заранее не- неизвестно, какое значение может принять u; rEntry (как если бы упомянутое значение вводилось пользователем), user Entry присваивается значение 0 просто для демон- демонстрации того, что пользователь вполне может ввести значение, которое не будет удовлетворять выражению условия. Листинг 7.8. Оператор do..whife, обеспечивающий по крайней мере один проход цикла. <html> <head> <title>JavaScript Unleashed</title> < /neacl> <body> <script language="JavaScriptl.2" type= javascript"> <• — Declare variables var userEntry = 0; var x я do{ document.writeln(x); x++; }while(x <= userEntry); </script> < /body > </html> break и continue Используя циклы, стоит обратить внимание на то, что по умолчанию цикл не прекращается, а будет выполнять- выполняться до тех пор, пока определенное условие не будет рав- равно false. Однако, иногда может потребоваться выйти из цикла до того, как он дойдет до закрывающей фигур-
Управл! структуры и организации цикло ной скобки. Подобное достигается за счет помещения в блок операторов внутри цикла break или continue. Оператор break завершает выполнение цикла, в то время как continue пропускает оставшиеся операторы текущей итерации, вычисляет очередное значение выра- выражения цикла (если таковое существует) и начинает вы- выполнение следующей итерации. Различия между этими двумя операторами продемонстрированы в листинге 7.9, который содержит достаточно тривиальный сценарий вычисления приближенного целочисленного значения квадратного корня числа п. ЛИСТИНГ 7.9. Использование операторов break и continue. <html> <head> <title>Onepa*popbi break и cantinue</title> </head> <body> <script type="text/javascript"> <! — // Объявление переменных var highestNum = 0; var n = 175 // Тестовое значение for (var i = 0; i < n; ++i) { document.write(i + "<br>")¦ if(n < 0) { document.write ("n не может быть ^отрицательным."); break; } if (i * i <= n) { highestNum = i; continue ; j document.write("<Ъг>Сделано!") ; break; J document, write ("<Ьг>Целочисленное значение, '**не превышающее квадратный корень") ; document.write(" из " + n + " = ' highestNum); // —> </script> </body> </html> Сначала i присваивается О, цикл начинается и ото- бражаегся значение i. Затем сценарий убеждается, что п не является отрицательным числом. Если п отрицатель- отрицательно, цикл прерывается и выполняется остаток программы после закрывающей фигурной скобки. Если п положи- положительно i умножается на то же i и результат сравнивает- сравнивается с п. Если результат меньше n, i сохраняется как наи- наилучшее текущее приближение квадратного корня из п. Затзм оператор continue пропускает оставшуюся часть текущей итерации и возобновляет работу цикла с момен- момента приращения i. Как только квадрат i превысит значе- значение п, сценарий пропускает continue и переходит к one- Глава 7 ратору break, который останавливает выполнение цик- цикла. Аппроксимация квадратного корня из 175 показана на рис 7.8. |-№1-|д:».т.>|1Н'1- №'|;Ш1\;У ™ у.11 eommunic иск . .: • '¦¦ ' ¦ ¦¦¦' ¦ ''¦¦'*- ¦¦"¦• ¦¦¦*:¦' ¦¦"¦¦ ш" ¦ ¦ ¦ ¦' ' ; ¦ :- '¦ •' ¦'¦'' ~":'\'::«>:- Сделано^ we, не превышающее квадратный корень ¦ 175 13 РИСУНОК 7.8. Внешний вид окна после того, как цикл переходит к оператору break и останавливается. Метки Начиная с версии JavaScript 1.2, в языке появился ме- метод обозначения более специфического места перехода при использовании операторов break и continue — мет- метки. Метку можно помещать перед любой управляющей структурой, которая содержит другие операторы. Это по- позволяет перейти из рамок условного оператора либо цикла на совершенно определенное место программы. Пример применения меток показан в листинге 7.10. Листинг 7.10. Использование меток. <html> <head> <title>McnonbSosaHKe MeTOK</title> </head> <body> <script language=" JavaScript!.. 2" type="text/ javascript"> .// Объявление переменных var stopX = 3; var stopY = 8 ; document. write ("Все пары х.у между @,0) и (") document, write (stopX + "," + stopY + ") :<br>") loopX: for (var x = 0 ; x < 10; ++x) ( for (var у = 0; у < 10; ++y) { document, write (" ("+x + "," + у +") ") ; if((x = stopX) is (y = stopY) ){ break loopX; document.write("<br>");
Базовое подмножество языка JavaScript Часть III >cument.write ("<Ьг>После завершения пик.i;i x '-•равно : " + х) document.writeln <"<Ьг>После завершения "цикла у равно : " + у) ; </script> </body> </html> В листинге 7.10 цикл for "помечен" пользовательс- пользовательским идентификатором loopX. Это позволяет покидать цикл for либо, наоборот, продолжать его вне зависимо- зависимости от вложенности. Та же метка loopX указывается в операторе break для завершения обоих циклов for. Без этой метки оператор break остановил бы только цикл, й значения для у. На рис. 7.9 показан ре- результат работы программы, когда х и у достигают, со- соответственно, значений 3 и 8. Все пары ху мвжяу@ 0) и C I @.0) @.1) @.2) @.3) @.4) @.5) @.6) @.7) @.8) @.9) 1,2X1.31 A.4) A.5) A.6 [20) B1) B.2) B.3) B.4) B5) B.< I 7) B.8) B,9) C.0) C.1) C.2) C.3) C.4) C.5) C.6) C.7) C.8) - ¦ ¦ циклах равно 3 1клзу рЭВно 8 РИСУНОК 7.9. Использованиеоператора\аЪе\ для выхода из вложенного цикла for. OnepaTopbiwith Оператор with применяется во избежание многократного повторения ссылки на объект при доступе к его свой- свойствам и методам. Любые свойства или методы в блоке with, которые JavaScript не может опознать, ассоцииру- ассоциируются с объектом, указанным в этом блоке. Синтаксис with таков: with (объект) { операторы ) Объект определяет, какой объект необходимо ис- использовать в случае отсутствия объектной ссылки в блоке операторов. Данный оператор особенно полезен при ис- использовании сложных математических функций, кото- которые доступны только через объект Math. Поскольку объект Math будет рассматриваться, начиная с главы 10, здесь показан оператор with для уже знакомого объекта Document. При вызове методов write() или writelnO, принадле- принадлежащих объекту Document, перед ними необходимо ука- указывать префикс document: document.writeln("Привет всем!"); Подобная методика применяется достаточно часто и в больших количествах. Для экономии на объеме кода все операторы, которые ссылаются на объект Document, стоит поместить в блок with. Как это сделать, показано в листинге 7.11. Поступая таким образом, можно изба- избавиться от назойливого префикса document в ссылках на методы и свойства документа. Обратите внимание, что title и URL — это свойства объекта Document, которые должны записываться как document.title и document.URL. При использовании опе- оператора with необходимость в ссылке на о( ; возника- возникает только один раз, тем не менее, достигается гот же са- самый результат, что и при наборе ссылки в каждой строке. На рис. 7.10 показан результат выполнения кода из листинга 7.11. ПРЕДУПРЕЖДЕНИЕ Internet Explorer 3.0 оператор with не поддерживает. 0- 1 ii. l» Ьяиий И* 1 Pebad Копи : ¦¦ ¦.:: '¦¦¦¦ SMnh "• ¦¦ html т i BBI BBI BBB a- .fiOP: _!Г.|*| a Цр«вгт! Заголовок этого документа выглядит как "Использование оператора"witi JRL этого документа выглядит как "file:///D|/books/jscript/7-1 оГ Теперь от префикса объекта можно избавиться раз и навсегда! 1 si <г РИСУНОК 7.10. Отображение информации с использованием оператора with. Листинг 7.11. Использование оператора with в JavaScript. <html> <head> <title>Hcnom>SOBaHMe оператора with</title> </head> <body> <script type="text/javascript"> <• — with(document) { write("Привет!"); write ("<Ьг>Заз7оловок этого докуне* ^выглядит как \"" + title + ' write ("<br>URL этого документе» выглядит как -\"" + URL + "\"."> ; write ("Теперь от префикса обгьек а можно |бавиться раз и навсегда!
Управляющие структуры и организация циклов Глава 7 I/ --> </script> </body> </html> ПРИМЕЧАНИЕ В зависимости от конкретного браузера, пример мо- может отобразить URL в закодированном формате. Оператор switch Оператор switch используется для сравнения одного зна- значения с большим количеством других. На первый взгляд упомянутая задача решается только за счет применения большого числа условных операторов, однако оператор switch тут будет гораздо уместнее. Он быстрее читается и позволяет определить заданный блок инструкций, выполняющийся в случае, когда соответствие не найде- найдено. В листинге 7.12 предполагается, что переменная request может изменяться в зависимости от требований пользователя. В данном примере request присваивается тестовое значение "Name". ПРИМЕЧАНИЕ пера-op switch до версии JavaScript - не существовал. Листинг 7.12. Оператор switch. <html> <head> <title>JavaScript Unleashed»:/title> </head> <body> <script language="JavaScriptl.2" type="text/javascript"> <• — J I Объявление переменных var request = "Name"; switch(request) { case "Logo" : document.write('<img src="logo.gif' alt="Logo">'); document.write("<br>"); break; case "Name" : document.write("Software Inc."); document.write("<br>"); break ,- case "Products" : document.write("MyEditor"); document.write("<br>"); break; default : document.write("www.mysite.com"); break; </script>- </body> </html> Вторая конструкция case совпадает с текущим зна- значением request, следовательно, выполнятся команды, перечисленные в ней. ]NDOWS\Deeklap\7S3X07 .L12.html «- ¦ ----- Software Inc. ¦ - J РИСУНОК 7.11. Использование оператора switch. Оператор break используется для прерывания даль- дальнейшего выполнения кода, оставшегося в switch. Если бы оператор break не использовался, оставшийся код выпол- выполнялся бы для каждого случая, независимо от соответ- соответствия между request и case. Из рис. 7.11 ясно, что request соответствует значению "Name", при этом на экран выводится название компании. Резюме Для принятия решений в JavaScript используются услов- условные операторы if и else, if обеспечивает выполнение ча- части программы на основе вычисления определенного ус- условия. Если условное выражение возвращает true, соответствующая часть программы выполняется, в про- противном случае — нет. Помещайте оператор else сразу после блока if, что- чтобы обеспечить выполнение следующего кода, когда вы- выражение в блоке if возвращает false. JavaScript допуска- допускает вложенные операторы if и if..else. Такой метод дает возможность задавать новые вопросы, основываясь на ответах на предыдущие вопросы. Циклы for применяются для многократного повторе- повторения одного раздела сценария. При объявлении цикла имеется возможность выбора начального значения пере- переменной, которая будет применяться внутри цикла. Мож- Можно также выбирать вариант изменения переменной, каж- каждый раз когда цикл завершается. Используя выражение условия цикла for, можно определять, когда остановить выполнение цикла.
Базовое подмножество языка JavaScript Часть II Используйте цикл for..in, если требуется выполнить набор операторов для каждого свойства объекта. JavaScript автоматически присваивает имя свойства выбранной переменной. С помощью такой переменной можно оп- определять операции над этим свойством. Используйте цикл while для многократного повторе- повторения раздела сценария. Потребуется лишь задать услов- условное выражение, которое должно возвращать true перед выполнением каждого цикла. Операторы break и continue используются для преры- прерывания любого цикла, break полностью завершает цикл, a continue останавливает текущую итерацию цикла, при этом программа переходит на начало следующей итера- итерации. Оператор with используется вместе с объектами JavaScript. Он позволяет сослаться на объект только один раз вместо многократных ссылок при обращени- обращениях к свойствам и методам. Внутри блока with можно ука- указывать имена свойств и методов объекта безо всякой ссылки на объект. И наконец, упомянем оператор switch. Этот опера- оператор позволяет определять все возможные значения дан- данной переменной для исполнения всех необходимых задач. Если текущее значение не равно одному из определен- определенных заранее, программа переходит к разделу default.
Функции В ЭТОЙ ГЛАВЕ Понятие функций Использование аргументов Дополнительные сведения о функциях Организация одной или множества функций отно- относится к одной из целей всех программ на JavaScript. В самом простом случае сценарий может читать или при- принимать данные, выполнять определенные операции на наборе данных либо отображать и отсылать данные. Как упоминалось ранее, для достижения требуемых целей можно использовать комбинацию базовых инструмен- инструментальных средств JavaScript или просто одно из них. Для связи с каким-то браузером сначала необходи- необходимо запросить его возможности и затем направить его по нужному пути. Для того чтобы у посетителя появилось желание неоднократно возвращаться на ваш Web-сайт, лучше всего предоставить ему возможность получать ин- информацию о всем новом и интересном, появившемся на сайте. Если вы, например, продаете какие-либо товары, при помощи JavaScript несложно подсчитать стоимость любой их комбинации для клиента и сохранить полу- полученные данные для отдела маркетинга. Выполнение подобного типа задач требует исполь- использования большого количества строк JavaScript. Некото- Некоторые разделы сценария должны выполняться непосред- непосредственно после загрузки Web-страницы в браузер. Другие части сценария, возможно, окажутся полезными, если проявят себя после того, как клиент введет определен- определенные данные в HTML-форму. Иногда бывает необходи- необходимо многократно (или даже неограниченное количество раз) использовать отдельные части сценария, при этом периодическое повторение одного и того же раздела программы неизбежно. Перечисленные проблемы приводят к идее разбие- разбиения сценария на части, из которых каждая служила бы одной конкретной цели. Каждая цель на шаг прибли- приближала бы к успеху в процессе выполнения JavaScript- сценария. Проверка достоверности введенных в HTML- форму данных — еще одна задача, которую сценарий мог бы выполнять, пока посетитель работает с Web- страницей. Поэтому имеет смысл разбить сценарий на логичес- логические разделы, каждый из которых предназначен для од- одной конкретной цели. Когда подходит время, определен- определенный раздел сценария начинает выполняться. JavaScript обеспечивает такую возможность, предоставляя струк- структуру, известную как функция. Понятие функций JavaScript-функция — это просто сценарий, отделенный от остальной части программы и имеющий свое имя. Используя это имя, другой сценарий может вызывать его в любой момент и сколь угодно раз. Некоторые языки программирования, например, C/C++ или Java, также используют функции, тогда как другие языки имеют те же самые семантические единицы, но называют их ме- методами, процедурами или подпрограммами. Все они делают в основном те же самые вещи, но имеют неко- некоторые различия. Функции служат одной цели — разделению задач, предназначенных для выполнения в одной программе. Можно считать функцию уведомлением JavaScript о не- необходимости выполнения конкретного списка связан- связанных команд и выдачи сигнала, как только это будет сделано. При вызове функции можно передать значения, на- называемые аргументами (arguments). Аргументы можно использовать в качестве переменных (variables) в пределах одного блока операторов. Как только данные присвое- присвоены переменной, становится возможной обработка дан- данных либо использование их в вычислениях. Создание функций Ниже приводится синтаксис объявления функции в JavaScript: function имяфункцил ([аргумент!] [оператора] [.. . , аргументы] ) {
Базовое подмножество языка JavaScript Часть II Ключевое слово function используется для определе- определения функции с именем имяФункции, которое служит в качестве идентификатора для набора операторов, заклю- заключенных в фигурные скобки. Имена аргументов, храня- хранящих передаваемые в функцию значения, заключаются в круглые скобки и отделяются друг от друга запятыми. С точки зрения программирования, аргументы пред- представляют собой переменные, которым можно присваи- присваивать литеральные значения, другие переменные или объекты, передаваемые в функцию при вызове. Даже в случае полного отсутствия аргументов все равно необ- необходимо после имени функции указывать пару круглых скобок, тем самым обозначая идентификатор как фун- функцию. Операторы в теле функции выполняются при каж- каждом вызове функции. Для повышения удобочитаемос- удобочитаемости строки внутри блока операторов выравниваются. Где объявлять функции Теоретически функцию можно объявлять в любом ме- месте в пределах раздела < script>. Существует единствен- единственное ограничение — нельзя объявлять функцию в пре- пределах другой функции или управляющей структуры. е в виду, одни блоки HTML-документа загружаются раньше других, равно как и любые сцена- сценарии, встроенные в эти HTML-блоки. В этой связи ре- рекомендуется объявлять функции HTML-документа в разделе <head>. Объявление всех функций в этом раз- разделе гарантирует, что функции будут доступны, если какому-то сценарию потребуется вызвать их неме/ но. В листинге 8.1 показана функция defaultColors(), объявленная внутри раздела <head>. Далее эта функ- функция вызывается в разделе <body> документа. Листинг 8.1 Объявление функции в разделе <head>. <html> <head> ocript type: <!-- function defaultColors () { document. writeln ("Внутри defaultColor () ") ; document . fgColor = "black"; document . bgColor — "white" ; </script> </head> <body> ocript type=" text/javascript" > <! — int. writeln ("Функции — это сценарии, '-•ожидающие выполнения! " ) ; defaultColors (); int. writeln ("Все дела переделаны."); </script> </body> </html> Вызов функции Листинг 8.1 демонстрирует вызов функции defaultColors() из второго раздела сценария. Это пример вызова функ- функции без аргументов. После полной загрузки HTML-до- HTML-документа функция сохраняется в памяти и находится там "в состоянии боевой готовности". Она не будет выпол- выполняться, пока главный раздел сценария не вызовет ее следующим оператором: defaultColors() В этой точке программа сразу же переходит на пер- первую строку функции <lefau!tColors(). После выполнения :сх трех строк программа возвращается назад к точке, в которой она покинула главный раздел, и продолжает работу там. Таким образом получается такой же эффект, как и при помещении всего кода функции непосредственно в конкретную позицию программы. Теперь, когда функ- функции присвоено имя, все, что потребуется сделать для выполнения тех же инструкций — использовать ее имя снова. Результаты описанного процесса показаны на рис. 8.1. Мне гократнос использование какого-то кода — вот наилучшее применение функции. Функции - это ¦'.» ¦' : . ожидающие выполнения! Btf/TprttJefauKCotor()Bc&A*na ^рэд&лань РИСУНОК 8.1. Повторное использование кода. ПРИМЕЧАНИЕ В отличие от свойства строки fontcolor, свойства до- документа fgcolor и bgcolor можно изменять без обнов- обновления или перезагрузки страницы в браузере. Использование аргументов Функции с аргументами не менее полезны. Аргументы дают возможность многократно использовать функцию
Функции' Глава 8 в разных задачах для достижения одних и тех же целей. Например, можно создать функцию, необходимость в ко- которой возникает много раз в ходе выполнения программы; однако при этом каждый раз при вызове функции требует- требуется изменять одно из значений внутри функции. ¦Один из способов решения упомянутой проблемы без задействования механизма аргументов связан с при- применением глобальных переменных, которые могут из- изменяться как вне, так и внутри функции. Программа станет запутанной, если те же самые переменные будут использоваться внутри более чем одной функции. Вы- Выгоднее создать функцию с аргументом, принимающим все необходимые значения. В листинге 8.2 показана функция, которая пользуется преимуществом примене- применения аргументов. Листинг 8.2. Использование аргумента в JavaScript-функции. <html> <head> <11Ь1е>Функции и apryMeHTbi</title> <soript type="text/ javascript"> <!-¦• function getBinary (anlnteger) { var result = ""; var shortResult = " for (var i=l; i <= 32; i++) { if(anlnteger S 1 = = 1) ( result = " + result; shortResult = result } else { result = " + result; anlnteger = anlnteger :i return(shortResult); </script> </head> <body>- <script type="text/javascript"> var binaryString = ' // Объявление переменной x x = 9; binaryString = getBinary(x); // Запись результатов на страницу 1 + х + ' в двоичном представлении: \п") ; document.writeln(binaryString); // Переопределение переменной х х = 255; binaryString = getBinary(x); // Запись результатов на страницу document.write ("Число " + х + ¦ в двоичном представлении: \п") ; document.writeln(binaryString); S переменной х 1 + x) ; </script> </body> </html> Когда функция вызывается как getBinary(x), она получает копию значения, хранящегося в переменной х. Такой процесс называется передачей по значению (passing by value). Значение присваивается anlnteger — локальной переменной данной функции. В дальнейшем эту переменную можно использовать в любом месте блока операторов как локальную. Как показано на рис. 8.2, если anlnteger изменяет значение внутри функции, это изменение не затрагивает значение переменной х, которая играет роль аргумента. Во* -1 \вп ¦ i . ¦ Число 9 в двоичном представлении К 01 Числи 255 в двоичном редставлении 11 Значение переменной х все еще равно: 255 РИСУНОК 8.2. Передача по значению не оказывает влияния на первоначальную Переменную. Обратите внимание, что anlnteger объявлять с ис- использованием ключевого слова var не требуется. JavaScript автоматически объявляет новую переменную при каждом вызове функции. Последний оператор в теле функции getBinary() — это return(shortResuIt). Функция может получать значе- значение, и точно также она может и возвращать определен- определенное значение. Оператор return возвращает одиночное значение в место вызова функции в программе. Возврат значения функции работает таким же образом, как и возврат значения вычисленного выражения. Приведен- Приведенный ниже оператор присваивает переменной binaryString значение, возвращаемое getBinary(): binaryString = getBinary(x); В данном случае переменной binaryString присваи- присваивается последнее значение shortResult. Можно использовать функции, возвращающие зна- значение, в обычных выражениях. Некоторые функции возвращают результат набора вычислений, тогда как
Базовое подмножество языка JavaScript Часть II другие — логическое значение, уведомляющее о том, все ли в порядке (см. листинг 8.3). Листинг 8.3. Функции, возвращающие значения, которые можно использовать в выражениях. <html> <head> <script type="text/javascript"> < ! ~ function isPhone(aString) { var aChar = null; var status = true; if(aString.length != 13) { status = false; lelse{ for (var i = 0; i <= 12; ) aChar = aString.charAt(i); If ( 1 = 0 && aChar == " (" )( continue; Уelse( If ( 1 = 4 66 aChar = ")" ) { continue; }else{ [ 1 = 8 66 aChar = "-" ){ continue; }else{ If ( parselnt(aChar.lO) >= 0 SS parseInt(aChar,10> <= 9 ){ continue; }else { status = break; I . : return(status); 1 </script> ¦</head> <body> <script type="text/javascript"> <! — var userlnput = "(800M55-1212"; if(isPhone(userlnput)) ( document.writeln("Спасибо за ввод вашего ^•номера телефона. ") ; document.writeln("Наш представитель '^подготовит вам") ; document.writeln("дополнительную "•¦информацию. ") ; }else( document.writeln("Пожалуйста, введите •¦¦номер телефона повторно,"); documen t.wri teln("используя формат -(###)###-####."); ) II—> </script> </body> </html> Вызов функции isPhone(userlnput) применяется как условное выражение в операторе if. Функция isPhone() возвращает логическое значение. Возвращенное значе- значение дает знать вызывающей программе, в корректном ли формате был введен телефонный номер. Это полезно для проверки достоверности данных, вводимых пользо- пользователями в HTML-форму. Из рис. 8.3 видно, что теле- телефонный номер был введен корректно, на что указывает соответствующее сообщение. Подробную информацию, касаемую проверки достоверности вводимых данных, можно найти в главе 29. : - ¦ ¦: . ,¦ ¦ f' ¦ ¦ ¦¦ Ш ¦Z вашего номера t ) информацию L Наш представитель подгот вам РИСУНОК 8.3. Использование функции в качестве условного выражения. Изменение количества аргументов Для функции устанавливается определенное количество аргументов. Несмотря на то что использование в точно- точности объявленного количества аргументов считается хо- хорошим стилем программирования, иногда возникает необходимость установки другого количества аргумен- аргументов. Иногда это требуется при вызове функции, кото- которая каждый раз использует одно и то же значение па- параметра и изменяет его только в специальных случаях. Если аргументы не передаются, следует использо- использовать их значения по умолчанию, определенные в теле функции. Это позволяет вызывать функцию без аргу- аргументов или определять значение, отличное от значения по умолчанию. В листинге 8.4 создается функция для отображения типичного приветствия, появляющегося, когда пользователь заходит на Web-страницу. Эта программа отображает одно из двух сообщений, в зависимости от того, известно ли ей имя посетителя. Если userName не равно null, это значит, что перемен- переменная определена. Такое возможно только если в функцию передается значение, например, Г-н Президент. Если аргумент функции равен null, переменная в привет- приветственном сообщении вообще не используется.
Функции Глава 8 Листинг 8.4. Функция, принимающая один аргумент или не принимающая ни одного аргумента. <html> <head> <title>*yHK4MH</ti tle> <script type="text/javascript"> <! — userName является необязательным function welcomeMessage (userName) { if (userName != null) { document, writeln ("\"Еще раз здравствуйте, " + userName + "A""); }else{ document, writeln ("\"Добро пожаловать на наш Web-сайт! \"") ; document, write ("ХпЕсли в функцию не перелается значение, ") ; document, writeln ("в результате отображения ") ; document.writeln ("переменной \"userName\" будет: ") ; document,writeln (userName) ; </script> </head> <body> <sciipt type="text/javascript"> <! — document .writeln ("Первый вызов welcomeMessage(),\n"); welcomeMessage("Г-н Президент"); ocument.writeln ("<НЯ>\пВторой вызов welcomeMessage () ,\n") ,* welcomeMessage(); // --> </script> </body> </html> Как показано на рис 8.4, ее использование приводит к отображению нежелательных данных. В зависимости от конкретного браузера, нежелательные данные будут отображаться как undefined или как пустой символ. «<*ir:A&xmm Первый вызов welcomeMessageQ. "Еще раз здравствуйте. Г-н Президент" Второй Bbl30BwelcomeMessage(). "Добро пожаловать на наш Web-сайт!" Если в функцию 11а передается значение. в результате отображения переменной "userName" будет, undefined РИСУНОК 8.4. Результат использования аргументов. В настоящее время JavaScript поддерживает операцию typeof, которая обеспечивает проверку, является ли userName неопределенным или равным null. Это иде- идеальный способ проверки, но он не поддерживается в некоторых устаревших браузерах. - 4 1-158 РЕСУРС , Новые возможности JavaScript подробно описывают- ся на сайте Netscape DevEdge по адресу http:// developer.netscape.com. Еще один случай связан с передачей в функцию большего количества аргументов, чем было определено в объявлении. Дополнительные значения при этом не теряются, а сохраняются в массиве arguments, который представляет собой свойство каждой функции. Все ар- аргументы, сохраненные в массиве, могут быть извлече- извлечены в пределах тела функции. Например, первый аргу- аргумент, переданный в функцию welcomeMessage, можно получить так: firstArg = welcomeMessage.arguments[0] Элементы массивов JavaScript нумеруются, начиная с 0. Второй элемент в массиве будет иметь индекс 1 и т.д. Для вычисления общего количества переданных ар- аргументов можно записать такую строку: numArgs = welcomeMessage.arguments.length В листинге 8.5 демонстрируются все упомянутые возможности, при этом в welcomeMessageO передается переменное количество аргументов. В данном случае функция welcomeMessage() приобретает следующий вид:
Базовое подмножество языка JavaScript Часть II welcomeMessage([имяПользователя] [, дополнительноеСообщение1] [,дополяятельноеСообщение2] . ..) Обратите внимание, что в листинге 8.5 ситуация, при которой userName неизвестно, однако дополнитель- дополнительные сообщения должны отображаться, все еще поддер- поддерживается. Переменной US& Name2 присвоено значение null для того, чтобы заполнить первый элемент в мас- массиве аргументов так, чтобы сообщение не рассматрива- рассматривалось в качестве имени пользователя. На рис. 8.5 пока- показано, что со всего этого вышло. СОВЕТ При коллективной разработке все сложные сценарии необходимо документировать, чтобы все, написанное лично вами, смогли понять и другие. Без простых и на- наглядных комментариев чтение приложения отымет го- гораздо больше времени. "Еще раз здравствуйте. "Давненько не "Добро пт ватьна наш Web-сайт!" "Не хотите пи стать членом клуба'*" "Стать ЧП9 клу'ба мажнои в онлайне!" РИСУНОК 8.5. Передача в функцию множества отображения множества сообщений. ептовдля Листинг 8.5. В функцию можно передать переменное количество аргументов. <html> <head> <t±tle>nepeMeHHoe количество аргументов в функции<^1^1е> <script type="text/ javascript"> // При определении welcomeMessage воспользуйтесь таким синтаксисом: // welcomeMessage ([userName] [, extraMessagel] [ ,extraMessage 2] ¦¦¦) function welcomeMessage (userName) { If (userName != null) { document.writeln("\"En(e раз здравствуйте, ' + userName + "A""); }else{ document.writeln("\"flo6po пожаловать на наш Web-сайт! \"") ; numArgs = welcomeMessage.arguments.length; // Если в функцию, помимо userName, передаются дополнительные аргументы, // отобразить каждый из них. if (numArgs > 1) ( for (var i = 1; i < numArgs; i++) { document.writeln("\""+welcomeMessage.arguments[i]+"\""); "Давненько не встречались! </script> </head> <body> <script type="text/javascript"> var userName = "Валера", extraMessage var userName2 = null; var extraMessagel = "He хотите ли стать членом клуба?"; var extraMessage2 = "Стать членом клуба можно и в онлайне! welcomeMessage(userName, extraMsg); document.writeln("<hr>"); welcomeMessage(userName2, extraMsgl, extraMsg2); // ~> </script> -< /body> </html>
Использование глобальных и локальных переменных В главе 5 рассматривались отличия между локальными и глобальными переменными. Кроме того, было проде- продемонстрировано, что глобальная переменная может из- изменяться в любом месте документа, в то время как ло- локальная — только в пределах функции, в которой она объявлена. Выбрать подходящий тип переменной мож- можно, следуя приведенным ниже рекомендациям: • Если предполагается, что значение переменной бу- будет использоваться и, возможно, изменяться в любой части программы (как внутри, так и вне функций), то переменная должна быть объявлена вне любой функции. Это называется созданием глобальной пе- переменной, поддающейся изменению в любой части программы. Лучше всего объявлять глобальную пе- переменную в разделе <head> HTML-документа, тем самым обеспечивая объявление переменной до лю- любого ее использования. В этом случае исчезает необ- необходимость повторного объявления этой переменной внутри какой-либо функции. • Если переменная необходима только в пределах кон- конкретной функции, там ее лучше и объявлять. Убеди- Убедитесь, что при объявлении переменной используется ключевое слово var. В этом случае ее значение гаран- гарантированно будет изменятся только в пределах функ- функции, JavaScript будет считать такую переменную' уникальной и отличной от любых глобальных пере- переменных, которые могут иметь то же самое имя. Для объявления переменных аргументов использовать ключевое слово var не требуется. Переменные, опре- определенные в объявлении функции, автоматически счи- считаются локальными и объявленными с ключевым словом var. • Если требуется использовать переменную только в пределах главного сценария, а не внутри каких-либо функций, объявляйте переменную где-нибудь вне Функции Глава 8 функций. К сожалению, нет средства, которое убе- уберегло бы сценарий от использования переменной внутри функций, поскольку переменная будет рас- рассматриваться как глобальная. Из-за невнимательно- невнимательности разработчика это может привести к перезаписи значений, хранящихся в переменных с одинаковы- одинаковыми именами. Во избежание подобного рода проблем всегда следуйте приведенным выше указаниям. Если требуется переменная, изменяющаяся в преде- пределах одной функции, но не нужная в другой функции, передавайте ее в эту функцию в качестве аргумента. Тем самым создается копия переменной и ее значе- значение присваивается переменной аргумента заданной функции. Поскольку функция в процессе работы изменяет свою собственную копию переменной, это никак не скажется на оригинале. Переменные аргу- аргумента автоматически объявляются как локальные для данной функции. Даже если переменная аргумента имеет то же самое имя, что и передаваемая перемен- переменная, изменения последнюю не затрагивают. Одно исключение все же есть — объекты. Когда в каче- качестве аргумента передается объект, он передается по ссылке, а не по значению. Вместо создания копии объекта функция использует первоначальный объект. Изменения, сделанные в свойствах объекта в преде- пределах функции, оказывают влияние на первоначальный объект. Примеры передачи переменных по значению приведе- приведены в листинге 8.6. Обратите внимание, как JavaScript раз- различает переменные с одинаковыми именами. Здесь пере- переменная пшпЬегВ передается в функцию doublePassedVar(). JavaScript автоматически создает локальную переменную, также названную пшпЬегВ. Даже при том, что эта локаль- локальная переменная имеет имя, совпадающее с глобальной, изменения ее значения никак не затрагивают глобальную переменную. Результаты выполнения кода из этого ли- листинга показаны на рис. 8.6. Листинг 8.6. Использование локальных и глобальных переменных. <html> <head> <title>JIoKcuibHue и глобальные nepeMeHHbie</title> <script type="text/javasoript"> <! — // Глобальные переменные, которые можно изменясь в любой функции. var numberA; // Глобальные переменные, которые можно изменять только в главном сценарии, var numberB; function doubleGlobalVar(){ // Это изменит значение глобальной переменной. numberA *= 2 ; function tripleLocalVar ()
Базовое подмножество языка JavaScript ,1 Часть II // Здесь используется переменная с именем, совпадающим с именем глобальной // переменной, однако JavaScript будет трактовать их как разные переменные. var nurrfoerA = 1; numberA *= 3 ; function doublePassedVar(numberB) { // Имя аргумента совпадает с именем передаваемой в функцию переменной. ,// Опять-таки переменные трактуются как разные. numberB *= 2 ; II—> </script> </head> <body> <script type="text/javascript"> numberA = 1 ; document.writeln("Начальное значение numberA: doubleGlobalVar(); tripleLocalVar(); document.writeln("Результирующее значение numberA: numberB = 1; document.writeln("Начальное значение numberB: ' + numberB); doublePassedVar(numberB); document.writeln("Результирующее значение numberB: ' + numberB); + numberA); + numberA); </script> </body> </html> Начальное значен,- numberA: 1 Результирующее Значение numberA: 2 Начальное значение numberB: 1 Результирующее значение numberB: 1 РИСУНОК 8.6. Полученные значения переменных numberA и numberB. Передача объектов по ссылке Формальное введение в создание пользовательских объектов JavaScript предоставляется в главе II. Имея дело с функциями, важно знать, что случается при ис- использовании объекта в качестве одного из аргументов в вызове функции. Когда в функцию передаются данные простых ти- типов, например, строки, числаилилогическиезначения, передача выполняется по значению. Это означает, что вместо оригинала функция использует копию перемен- переменной. Любые изменения, произведенные в копии, ори- оригинал не затрагивают. С другой стороны, когда в функцию передается объект, то передача происходит по ссылке. Следователь- Следовательно, функция будет изменять первоначальный вид объек- объекта. Зная это, простые типы данных можно поместить внутрь объекта, если требуется передать переменную по ссылке (см. листинг 8.7). Листинг 8.7. Передача по ссылке по значению. <html> <head> <title>IIepena4a по ссылке по 3Ha4eHKio</title> <script type="text/javascript"> ,// Поместить стандартный тип integer // в объектную оболочку function intobject() { this.i; return this ; function start() { // Два способа хранения данных типа integer var I ; var mylntobject = new intObject(); // Присвоить начальные значения i = 0; mylntobject.i = 0; // Отобразить текущие значения document.write("<Ьг>До<Ьг>"); document.write("i = " + i) ; J
Функции document.write("<br>"); document.write("mylntObject = " + mylntObject.i); document.write("<br>"); // Передать переменные в функцию modify(i, mylntObject) ; // Отобразить текущие значения document.write("<Ьг>После<Ьг>"); document.write("i = " + i) ; document.write("<br>"); document.write("mylntObject = " + mylntObject.i); document.write("<br>"); function modify (n, obj) { II—> </script> </head> <body> Ocript type="text/javascript"> <! — start () ; II—> </script> </body> </html> Функция intObject() используется для помещения переменной i в объектную оболочку. Экземпляр объек- объекта создается следующим образом: var mylntObject = new intobjectf) Теперь mylntObject может использоваться для обра- обращения к переменной i при помощи такого кода: mylntObject.i Это также позволяет передавать в функцию числовое значение по ссылке. Функция modify() демонстрирует различия между изменением простого типа данных и из- изменением объекта. На рис. 8.7 показано, что начальное значение i не изменилось, в то время как на первоначаль- первоначальное значение mylntObject.i воздействие было оказано. Глава 8 шую выгоду она дает в плане повторного использования кода. Lkt -OperaSoftVMl Auto Imported Items Automobiles JBum«sand Finance Complement»? Heath f"_ompuler Genet gl lefore myIntObject= 0 ¦Aficr i = 0 mybitObject= 1 РИСУНОК 8.7. Передача пользовательского объекта JavaScript по ссылке. В отличие от циклов, которые повторяются много раз в определенной последовательности, функцию мож- можно повторно использовать в любое время, просто обраща- обращаясь к ее имени. Создание функций, которые предназна- предназначены для одной цели, но полезны в многих ситуациях, — практичный и предусмотрительный подход. Например, в листинге 8.4 функция welcomeMessage() служит одной и той же цели сразу в нескольких слу- случаях в процессе выполнения программы. Функция welcomeMessage() пригодилась в большем количестве ситуаций, т.к. в листинге 8.5 был создан более гибкий список аргументов. Она еще служит все той же цели, но это лучший кандидат на повторное использование в более гибкой форме. Вспомним, что функции можно хранить во внешних JavaScript-файлах. Включают эти файлы, используя ат- атрибут src дескриптора <script>. В результате существен- существенно снижаются временные затраты разработчика по рас- распространению новой версии функции на весь сайт, поскольку ему потребуется отредактировать функцию только один раз. Дополнительные сведения о функциях Рекурсивные функции В главе рассматривались основные понятия, касающи- касающиеся функций. Без функций JavaScript был бы просто языком написания сценариев, который использовался бы только для очень простых сценариев. К уже сказан- сказанному вполне уместно добавить, что функции могут по- повторно использоваться и быть рекурсивными. Повторное использование функций Функция — наиболее подходящий инструмент для де- деления приложения на логические части, но еще боль- Функции JavaScript могут быть рекурсивными, т.е. вы- вызывать сами себя. Вычисление факториала — лучший способ демонстрации рекурсивного процесса. Ввиду того что JavaScript не имеет встроенной операции фак- факториала, их придется вычислять самостоятельно, при- причем с использованием механизмарекурсивных функций. Для нахождения факториала любого положительно- положительного целого числа п требуется просто найти произведение всех целых чисел от 1 до п. Например, факториал чис- числа 6 (записывается как 6!) вычисляется следующим об- образом:
Базовое подмножество языка JavaScript Часть II 6! = 6x5x4x3x2x1= 720' 7 • вычисляется так; 7! =7x6x5x4x3x2x1 = 5040 На основе сравнения этих двух выражений можно записать общую формулу, которая будет использовать- использоваться в создаваемой функции. Обратите внимание, что 7! ни что иное как 7х 6!, Для любого положительного це- целого числа п справедлива запись n! = n х(п - 1)!. Пер- Первая итерация выглядит так: 7! = 7 х G - 1)! = 7x6! Теперь необходимо остановиться и вычислить 6!. Поступая аналогичным образом еще шесть раз, получим окончательное решение. Однако гораздо эффективней воспользоваться рекурсивной функцией, например, та- такой: function getFactorial(n) { var result; if (n > 0) { result = n * getFactorial (n — 1) ; } else if (n=O) { result = 1 ; } else { result = null; f return(result) Функция сначала сравнивает п с нулем. Если выра- выражение п > 0 истинно, функция умножает п на резуль- результат, возвращенный из вызова этой же функции с дру- другим аргументом, в данном случае, п - 1. Вложенные вызовы функции getFactorial() продолжают ожидать, пока пне станет равным 0. В этот момент наиболее вло- вложенное выполнение функции завершается и возвраща- возвращает первое значение. JavaScript возвращается назад и за- завершает каждую вложенную функцию, пока не достигнет первого вызова getFactorial, после чего получится окон- окончательный результат. Разработка полезных функций — один из наиболее существенных и интересных аспектов программирова- программирования. После того как функция проверена в действии, стоит возвратиться и подправить ее, попытаться сделать более гибкой. После не забудьте убедиться, что функ- функция все еще решает заданную цель и не делает ничего неожиданного. Резюме Получив определенный опыт создания функций, мож- можно переходить к следующему захватывающему шагу в программировании на JavaScript — созданию пользова- пользовательских объектов. Эта тема рассматривается в главе 11. Однако перед этим необходимо еще многое изучить касательно объектов, встроенных в HTML и JavaScript. Кроме того, JavaScript имеет множество встроенных функций, доступных в любой момент. Перечисленным темам посвящена глава 10. JavaScript-функции помогают достичь многих целей. Они позволяют сохранять код так, чтобы он не выпол- выполнялся сразу же после загрузки документа. Использова- Использование аргументов дает возможность легко дублировать код и применять тот же самый код для выполнения оди- одинаковых операций на различных наборах данных. Ниже приводится краткий список возможностей функций и напоминаний о том, как каждая из этих функций вы- выполняется. ¦• Функция — это набор JavaScript-кодов, сгруппиро- сгруппированных и имеющих собственное имя. Для объявле- объявления функции напишите ключевое слово function, за которым должно следовать имя функции, набор круглых скобок и сценарий, который функция будет содержать. Имя функции должно выбираться в со- соответствие с общими правилами именования пере- переменных. • Функции могут объявляться в любом месте HTML- документа, но обязательно внутри пары дескрипто- дескрипторов <script>. Лучше всего объявлять функции в раз- разделе <head> документа. • Для вызова функции напишите ее имя вместе с на- набором круглых скобок. В эти круглые скобки можно заключать любые аргументы, которые будут переда- передаваться в функцию. • Аргументы передаются по значению. Функции мо- могут принимать переменное число аргументов, неза- независимо от того, как функция была объявлена. Каж- Каждая функция имеет массив, называемый arguments. Этот массив используется для извлечения значений переданных аргументов. Функции могут возвращать значения. Функции, воз- возвращающие значения, можно использовать в выраже- выражениях. • Нет необходимости объявлять переменные аргумен- аргументов. Они автоматически объявляются как локальные переменные, каждый раз когда функция вызывает- вызывается. Для объявления глобальных переменных в пре- пределах функции не следует использовать ключевое слово var. В данном случае потребуется только ини- инициализация переменных. • Функции, решающие одну цель, однако достаточно гибкие, чтобы иметь дело с различными порциями данных — верные кандидаты на повторное исполь- использование. 1 • В JavaScript функции могут вызывать сами себя. Фун- Функции подобного рода носят название рекурсивных.
Объекты со стороны клиента В ЭТОЙ ГЛАВЕ Понятие объекта Объекты JavaScript Дополнительная информация об объектах В предыдущих главах книги рассматривались базо- базовые элементы языка JavaScript. Но это далеко не все. Без сомнений, квинтэссенция JavaScript со стороны клиен- клиента — это объектная модель. Поэтому в настоящей главе будет дано общее представление объектной модели JavaScript и всех существующих на данный момент язы- языковых объектов. Перед детальным изучением JavaScript-объектов по- потребуется выполнить краткий обзор некоторых основ- основных концепций объектно-ориентированного програм- программирования (object-oriented programming — ООП). JavaScript не настолько объектно-ориентированный, как Java или C++, но и он основан на объектах. Поэтому знание соответствующей терминологии будет хорошим фундаментом для понимания использования JavaScript- объектов. После раскрытия основных понятий ООП эта глава переходит к рассмотрению того, что собой представ- представляет объектная модель JavaScript, а также (что еще важнее) — того, чем она не является. Наконец, в зак- заключительной части главы приводится краткое описание всех объектов объектной модели. Понятие объекта Человеку, недостаточно хорошо знакомому с объектно- ориентированными концепциями, может показаться, что разработчики, пользующиеся ООП, говорят на другом языке. Действительно, термины наподобие ООП, мето- метода, свойства на первых порах выглядят пугающе для того, кто привык программировать с помощью функций или макрокоманд. Однако как только вы найдете время для изучения ООП, вы увидите, что его легко понять интуитивно. В этом разделе рассматривается ряд основ- основных концепций, в том числе объекты, свойства и мето- методы. Объекты Программы обычно разрабатываются в специальных коммерческих целях. Например, система менеджмента предназначается для обработки заказов со стороны кли- клиентов. Коммерческие прикладные задачи, в дополнение к требованиям конечного пользователя, формируют "мир проблем", или "пространство проблем", или то, на что ссылаются как на "предметную область" программного обеспечения. Эта область также включает и такие ком- компоненты, как графический пользовательский интерфейс (GUI). В конструкции объектно-ориентированных @0) приложений объекты являются центральными логичес- логическими блоками. Зачастую объекты в коде программы - это представления реальных объектов, находящихся в пространстве проблем. При этом существует возмож- возможность формирования вспомогательных объектов для решения специальных проблем. Объектом может быть любое понятие из следующе- следующего списка: • Материальная или видимая вещь в предметной об- области, например, заказ или клиент. Если разраба- разрабатывается программное обеспечение для автомо- автомобильного бизнеса, вероятными объектами будут продаваемые автомобилей, модели автомобилей, слу- служащие, клиенты и т.п. • Абстрактная концепция, существующая только в уме разработчика, или что-то, что можно представить умозрительно. Например, при разработке приклад- прикладных программ для химиков потребуются химические структуры объектов типа молекул, атомов, химичес- химических моделей и пр. Дату и время также можно рассмат- рассматривать как умозрительные объекты, т.к. они, конеч- конечно же, не материальны. Объект Math в JavaScript — еще один хороший пример чистой логической кон-
Базовое подмножество языка JavaScript Часть II цепции. В объекте Math содержатся расширенные ма- математические функции (арифметические и тригоно- тригонометрические) для обработки чисел в JavaScript. • Видимый объект графического пользовательского ин- интерфейса (GUI-объект). JavaScript содержит много различных GUI-объектов, например, окна, фреймы, кнопки, поля ввода. Исторически сложилось, что ОО модель базируется на концепции структур данных. Структуру данных мож- можно рассматривать как более сложный тип данных. Струк- Структура данных очень похожа на идею объекта. Она пред- представляет собой модель абстрактной концепции в информатике для решения простых технических задач программирования. Структура данных является контей- контейнером, содержащим соответствующие данные о перемен- переменных и определенных для них операциях. Существует множество примеров того, что в книгах по компьютерным наукам объектами называют по суще- существу структуры данных, типа протоколов, массивов, ком- комплексных чисел или стеков. Стек — это контейнер для хранения значений данных; работа с ним, в основном, подобна работе со стопкой бумаги. В каждый момент времени стек может хранить только один элемент дан- данных, который всегда помещается поверх других элемен- элементов. Кроме того, удалять элемент данных можно только из верхней позиции стека. Другие популярные структуры данных — строки и даты, которые также рассматриваются в JavaScript как базовые объекты. Строка — это совокупность одиночных символов. Строка считается одиночным объектом даже при том, что некоторые строковые функции извлекают подстроки из строк. Объект Date включает в себя зна- значения данных, содержащих дату и время. Объект содержит значения данных, необходимые для описания его природы (свойства объекта) и функции, которые он может выполнять (методы объекта). Можно, рассматривать объект как нечто, имеющее определенные границы, как показано на рис. 9.1. Ядро объекта фор- формируют его значения данных. Элементы данных объек- объекта описывают специальные характеристики объекта и его идентификацию. В ОО терминах объектные элементы данных называются свойствами ('или атрибутами). Вообще говоря, объекты поддерживают множество функций. Видимые извне функции объекта формируют его поведение. В ОО терминах объектную функцию ча- часто называют методом. Метод — это часть исходного кода, выполняющая отдельно взятую задачу, которая относится к важным характеристикам объекта. Метод представляет собой функцию объекта, к которой мож- можно обратиться. Другими словами, методы объекта определяют его поведение, которое проявляется его видимыми и пред- предсказуемыми действиями. Структура объекта на рис. 9.1 показана в виде пиро- пирога с начинкой. Методы объекта размещаются во внеш- внешнем круге, поскольку они видимы для других объектов, т.е. могут вызываться и выполняться для данного объек- объекта. Атрибуты находятся во внутреннем круге. Рассмотрим в качестве примера объекта автомобиль. В объектно-ориентированном пространстве автомобиль представлен как объект туСаг. Поскольку конкретный автомобиль — это красный Renault 19 выпуска 1992 г., его атрибуты выглядят так: make model age color Renault 19 1992 красный Автомобиль может быть припаркован или находить- находиться в движении. Это важные для него функции. На рис. 9.2 приведено графическое представление автомобиля как объекта. В дополнение к специфическим характеристикам и идентифицирующим значениям, атрибут объекта может также отображать состояние объекта или роль, которую объект играет в данное время. Состояние и роль — спе- специальные зависящие от времени характеристики объек- объекта. Состояние (state) — вид элемента данных, который изменяется во времени и в общем случае показывает текущее значение для объекта. РИСУНОК 9.1. Графическое представление объекта. РИСУНОК 9.2. Графическое представление автомобиля как объекта. Добавим в список еще один атрибут шуСаг — position, который всегда содержит текущее географическое поло-
Объекты со стороны клиента жение автомобиля. Атрибут position — типичный при- пример атрибута состояния. Служащий может стать руководителем группы или начальником отдела в любой момент его профессиональ- профессиональной карьеры. Объект "служащий", таким образом, будет содержать атрибут профессионального состояния, хра- хранящий различные должности (руководитель группы или начальник отдела), которые служащий мог бы занимать. Рассмотрим пример с использованием факториалов. На рис 9.3 показан простой графический пользователь- пользовательский интерфейс для вычисления факториалов. Исходный код HTML-формы приводится в листинге 9.1, Обратите внимание, что исходный код вычислений в этот листинг не включается. Листинг 9.1. Программа вычисления п! <body> <h3> Вычисление факториала для целых положительных чисел </h3> <hr> <form> Введите целое число: <input type="text" name="fn" size="> результат: <:.nput type="text" name="f result" size=0"> <input type="button" name="compute" value="Вычислить n!" onClick="xcompute (this . form) "> </fotrm> </body> Вычисление факториала для целых положительных чпеел Зведите ^ i ос число J ' результат | РИСУНОК 9.3. Графический пользовательский интерфейс для задачи вычисления п! В JavaScript атрибуты объекта называются свойства- свойствами (properties).Например, кнопка compute в приведенном выше примере — GUI-объект JavaScript. Кнопка имеет свойстза name и value. В рассмотренном примере Глава 9 HTML-документа (листинг 9.1) свойства определяют- определяются атрибутами name и value. Пользователь может щелкать на кнопке GUI, следо- следовательно, объект compute поддерживает функцию click. Функция click позволяет работать с объектом compute че- через сценарий. Все функции объекта определяют его по- поведение. В 00 терминах функция объекта зачастую на- называется методом. Однако в JavaScript применяется ключевое слово function. На рис. 9.4 приводится графи- графическое представление объекта JavaScript в виде все того же пирога с начинкой. РИСУНОК 9.4. Графическое представление объекта JavaScript. Встроенный объект "строка" — это специальный тип объекта. Строку myString можно создать с помощью var. Инструкция var создает новые переменные в JavaScript,, например: var myString = "Мой и только мой текст. Исключительно для целей демонстрации объекта строки"; myString, как и все строки, имеет свойство length. Атрибут length содержит длину строки myString, в дан- данном случае — число 75. Строки имеют несколько раз- различных методов (подробности можно найти в главе 10), в том числе blink(). обеспечивающий мигание строки. Рассмотрим такой дескриптор HTML: <blink> Мой и только мой текст. Исключительно для целей демонстрации объекта строки </blink> Следующая строка создает мигающий на экране текст "Мой и только мой текст. Исключительно для целей демонстрации объекта строки": myString.blink(); Свойства объекта могут содержать простые типы пе- переменной, такие как символы, целые числа и т.д., а так- также другие объекты (см. рис. 9.5). Например, объект myCar может быть определен че- через атрибуты make, model, year, owner, где owner —
Базовое подмножество языка JavaScript Часть II объект персоны, определенный в свою очередь через атрибуты name, age и address. Включение объектов в атрибуты других объектов обычно называют агрегирова- агрегированием (aggregation) или отношением "целое-часть" (whole- part). Выражение "целое-часть" показывает типичный пример содержания, когда машина состоит из несколь- нескольких меньших частей, как автомобиль — из двигателя, четырех колес и т.д. Инкапсуляция РИСУНОК 9.5. Графическое представление содержания объектов. В JavaScript имеется множество различных объектов, среди которых String, Date, Button, Math. Их все мож- можно использовать. Можно даже иметь несколько различ- различных объектов, принадлежащих одному типу. Например, рассмотрим HTML-форму, содержащую несколько кнопок. Каждая кнопка обладает одними и теми же свойствами и методами; т.е. каждая кнопка име- имеет значение и поддерживает метод click. Объект кнопки — это только план конструкции реальных кнопок фор- формы. Подобная спецификация конструкции в 00 терми- терминологии называется классом (class). Различные встроен- встроенные объекты в JavaScript фактически и формируют набор классов, которые можно многократно использо- использовать. Такой набор классов называется библиотекой клас- классов (class library). Поскольку JavaScript в действительно- действительности не имеет дело с классами, как это имеет место в истинных объектно-ориентированных языках, на сово- совокупность встроенных объектов в JavaScript зачастую ссылаются как на библиотеку объектов JavaScript (JavaScript object library). * СОВЕТ ¦ ¦¦ ¦¦' ¦ ¦'-1-0-4 . ¦¦"^«S*- - Для того чтобы сберечь время и силы, затрачиваемые на разработку программы, используйте побольше JavaScript-объектов в подходящих ситуациях. Тщатель- Тщательно изучите библиотеку объектов JavaScript. He изоб- изобретайте собственные типы объектов, если в этом нет необходимости. Повторное использование уже суще- существующих программных компонентов — одна из наибо- наиболее выгодных стратегий в объектно-ориентированном программировании. Атрибуты данных и функции объекта формируют одну неделимую сущность, как показано на рис. 9.6. На рис. 9.6 показано то же графическое представление объекта, которое уже встречалось ранее на рис. 9.1. Информация о внутренней работе объекта должна быть сокрыта. РИСУНОК 9.6. Графическое представление объекта в виде инкапсулированной сущности. Объект взаимодействует с внешним миром через свои опубликованные общедоступные методы, которые и формируют интерфейс. Рассмотрим еще раз объект myCar. ¦Опубликованными методами объекта myCar являют- являются park и drive; они представляют собой функции, кото- которые поддерживает объект myCar. Эти методы называются общедоступными (public), поскольку они доступны извне. Они могут вызываться другими объектами для реализа- реализации своих задач. Интерфейс объекта — это, по сути дела, набор предлагаемых им общедоступных методов. Противоположностью общедоступных методов явля- являются приватные (private) методы. Приватные методы — это вспомогательные функции объекта. Они использу- используются только внутри конкретного объекта. Приватные методы не могут вызываться извне. JavaScript не поддер- поддерживает приватных методов, так что все функции, объяв- объявленные в объекте, являются общедоступными. Даже атрибутами объекта нельзя управлять извне. В контексте разработки программного обеспечения такой принцип называется сокрытием информации (information hiding). Вернитесь к объекту myCar и расширьте список существующих атрибутов (make, model, age, color) допол- дополнительными атрибутами, например, engine и wheels. Правда, лично я особенно не интересуюсь типом колес, которые имеет myCar. Единственная вещь, которая дей- действительно важна для меня, — что мой автомобиль ра- работает хорошо и управляем. Смена типа двигателя не должна повлиять на рабочее состояние myCar. Кроме того, тип нового двигателя меня ничуть не интересует. Все что я только хочу — так это только ездить на myCar.
Объекты со стороны клиента Построение абстрактного представления объекта должно предшествовать решению о его реализации. Из- Изменения исходного кода внутренностей объекта не дол- должны оказывать влияние на абстрактное представление. Для создания хорошего и простого программного про- проекта необходимо, чтобы никакая часть сложного прило- приложения не зависела от внутренних кодов любого объек- объекта, задействованного в приложении. Инкапсуляция и сокрытие информации приносят несомненную пользу в двух важных аспектах: • Будем считать объект небольшим программным ком- компонентом. Его легко использовать во многих ситуа- ситуациях и местах программы. Повторное использование программных компонентов хорошо поддерживается через механизм инкапсуляции. Возможность повтор- повторного использования — одно из самых больших пре- преимуществ ООП. При правильном использовании это позволит существенно сэкономить время и деньги при разработке больших программных систем. ¦ • Сокрытие подробностей реализации объекта дает про- программисту возможность позже изменять представле- представление данных без изменений представления объекта во внешнем мире. То же самое можно сказать и об из- изменениях внутренних методов. Интерфейс объекта остается тем же самым. Исходный код, касающийся организации взаимодействия объектов, остается тем же самым. Это означает ощутимое сокращение уси- усилий ю поддержке объектов, равно как и большую ус- устойчивость архитектуры программной системы по сравнению с традиционными приложениями. Сообщения Если требуется, чтобы объект сделал что-нибудь полез- полезное, ему посылают соответствующее сообщение. Сооб- Сообщение приводит к вызову определенной функции объек- объекта. На рис. 9.7 показана передача сообщений между объектами. Например, если требуется установить текущее время в приложении, создается новый объект currTime типа Date и в нем устанавливается текущая дата и время: var currTime = new Date () ; РИСУНОК 9.7. Графическое представление передачи сообщений между объектами. Инструкция var просто создает новую переменную. Новые объекты создаются методом объектного типа new. Глава 9 Метод new в данном случае создает новый объект Date. Этот новый объект автоматически получает текущую дату и время. Поскольку в инструкции применена опера- операция присваивания (=), переменная currTime будет содер- содержать объект типа Date с текущей датой и временем. Если необходимо установить текущее время в часах и минутах, то это делается так: var hours ; var minutes ; hours = currTime.getHours(); minutes = currTime. getMinutes () ; Все, что потребуется предпринять — это отправить сообщение getHours объекту currTime и в качестве ре- результата получить количество часов. Затем послать со- сообщение getMinutes, чтобы получить количество минут. Сообщения JavaScript — это, по сути дела, вызовы фун- функции. Из документации по базовым объектам JavaScript ясно, что объект типа Date понимает сообщения getHours и getMinutes. Это означает, что объект типа Date инициирует вызовы функций »etHours() и getMinutes(). При создании пользовательских объектов необходи- необходимо также определить и методы. Внутри одного метода может возникнуть потребность в других объектах для гния некоторых задач. Например, в приложении для автомобильного бизнеса имеется объект currSale, ответственный за автомобильную продажу, и метод getSaleData(), выдающий данные по продажам. Внутри функции getSaleData() присутствуют обращения к объектам типа С ir и Customer. Обоим объектам посы- посылаются сообщения с целью получения необходимой ин- информации. Если продолжить разработку данной концеп- концепции, можно увидеть, что объектно-ориентированное приложение — это мир объектов, поддерживающих связь через механизм сообщений. Классы Объект — это реально существующая сущность в про- программе. Например, okButton, myWindow, currTime - объекты. Объект — конкретная сущность, существующая во времени и пространстве, а вот класс представляет собой только лишь абстракцию нескольких подобных объектов, как показано на рис. 9.8. 1РИСУН0К 9.8. Графическое представление класса.
Базовое подмножество языка JavaScript Часть II Объекты с одинаковыми свойствами и поведением формируют класс или объектный тип. Класс содержит конструктивный план принадлежащих ему объектов. Это означает, что класс определяет количество, имена и структуры атрибутов и методов. Кроме того, класс обеспечивает выполнение функ- функций. Новые объекты создаются прежде всего по опре- определенному конструктивному плану. Каждый объект — член некоторого класса; говорят, что объект является эк- экземпляром (instance) данного класса. Свойство объекта также называется переменной экземпляра (instance variable) класса или объекта. Например, ваш автомобиль, мой автомобиль и авто- автомобиль вашего соседа — все являются автомобилями, хотя имеют разные марки, года выпуска и цвета. Каж- Каждый автомобиль обладает маркой, названием модели, годом выпуска и цветом. Кроме того, каждый автомо- автомобиль может двигаться или находиться в месте парковки. Возможности и функции у них одинаковые. Класс саг описывает характеристики данных и методы для всех ав- автомобилей. Язык JavaScript нельзя назвать объектно-ориентиро- объектно-ориентированным языком, основанным на классах, поскольку он не имеет операторов для работы с классами. Однако, JavaScript содержит похожую концепцию — объектный тип. Клиентские типы объектов включают в себя различ- различные объекты GUI или базовые объекты типа Date, String, Math. Новые объекты создаются с помощью ме- метода new. Это верно для всех объектов. Следующий код создает объект currTime как новый экземпляр объекта типа Date: var currTime = new Date (); В JavaScript существует возможность определения собственных объектных типов. Например, если система должна отображать значения времени, можно создать новый объект типа Clock. Объект Clock должен содер- содержать часы и минуты, следовательно, свойствами объек- объекта Clock будут hours и minutes. Методы, которые объект Clock должен выполнять — dispIayTime() и setTime(). Следующий фрагмент демонстрирует определение объекта типа Clock: function Clock (hours, minutes) { this.hours = hours; this.minutes = minutes; this.setTime = setTime ; this. displayTime = displayTime; function setTime (hours, minutes){ this.hours = hours; this.minutes = minutes; function displayTime(){ var line = this.hours + + this .minutes; document.write <"<пгХр>Текущее время: " + line) ; 1 JavaScript является языком, основанным на экземп- экземплярах, поскольку в нем нет конструкций классов. Осно- Основанный на экземплярах (instance-based) — это термин ООП, означающий, что язык программирования содержит объекты, но не классы. JavaScript не особенно хорошо структурирован в этом смысле. Он не содержит классов, но имеет концепцию типа объекта. Кроме того, новые объекты не могут со- создаваться через существующие; они могут создаваться только с помощью new. Компания Netscape называет JavaScript языком программирования, основанным на экземплярах. Обратите внимание, что оператор function в JavaScript предназначен сразу для многих целей. Создание новых типов объектов означает определение функции с именем объектного типа в качестве имени функции. 13 резуль- результате код всегда выглядит немного запутанным с точки зрения читателя. Свойства нового типа объекта объяв- объявляются как параметры функции. Это означает, что есть только один конструктор для нового класса. Конструк- Конструктор — метод класса, который создает новый объект в соответствие с шаблоном класса. Конструктор инициа- инициализирует новый объект с определенными значениями данных согласно параметрам, передаваемым в конструк- конструктор. В следующем коде показан шаблон для объявления нового типа объекта в JavaScript: function Ob jectType (instVarl, instVar2, ...){ this.propertyl = instVarl; this.property2 = instVar2; this. me thodl = functionl ; this.method2 = ?unction2; functionl (paraml, param2, . . .) { here goes the implementation ?unction2 (paraml, param2, . . .) { here goes the implementation Специальный объект this указывает на текущий объект. Свойства и методы нового объекта определяют- определяются при помощи присваивания this. Начальные свойства для нового объекта передаются в качестве параметров создающей функции; в шаблоне они названы instVarl и instVar2. В определении типа объекта присутствуют только имена методов (methodl и method2). Реализация методов, таких как функции (function 1 и function2), рас- рассматривается позже. Объявления новых объектных типов лучше помещать в раздел <head> HTML-документа, чтобы они читались в начале процесса загрузки документа. Это гарантиру-
Объекты со стороны клиента Глава 9 ет, что объявления класса будут известны во время ин- интерпретации остальной части программы. Код, выпол- выполняющий действия, обычно помещают в раздел <body> HTML-документа. Для более полного понимания классов рассмотрим листинг 9.2, делающий короткое описание класса Clock в простом, но полном HTML-документе. Листинг 9.2. Создание объекта Clock и отображение результатов на Web-странице. <html> <head> <title>JavaScript Unleashed</title> ocript type="text/javascript"> function Clock (hours, minutes) { this, hours = hours; this, minutes = minutes; this . setTime = setTime; this. displayTime = displayTime; i function setTime (hours, minutes) { this.hours = hours; this, minutes = minutes; function displayTime (> { var line = this.hours + ":" + this.minutes;; document.write ("<Ьг>Текущее время: " + line) ; ,1 II—> </script> </head> <body> <script type="text/javascript"> var currTime = new Date (> ; var myClock = new Clock (currTime. ge tHours () , ^currTime. getMinutes ()) ; myClock.displayTime(); II—> </script> </body> </html> При помощи следующего оператора в разделе <body> документа создается и инициализируется в соответствии с текущим системным временем новый объект myClock типа Clock: var myClock = new Clock (currTime.getHours (), currTime.getMinutes() ); «ПРИМЕЧАНИЕ !' /V . ' Ч| ; , !% Поскольку JavaScript — это язык, основанный на экзем- экземплярах, в нем имеется возможность расширения лю- любого существующего объекта новыми свойствами и ме- методами во время выполнения. При этом новые возможности добавляются только в один определен- определенный объект и не затрагивают другие объекты того же типа. Объекты JavaScript Как обсуждалось в начале этой главы, JavaScript — не объектно-ориентированный язык, а язык, лишь только основанный на объектах. Он содержит понятия объек- объектов, свойств, методов и инкапсуляции. Однако он не поддерживает строгую типизацию, поскольку перемен- переменные не объявляются вместе с типами. Например, пере- переменная currTime объявляется так: var currTime; Здесь не указывается тип переменной (например, int, char или какой-то объектный). В переменную currTime можно поместить значение любого типа, в том числе и объектного. Интерпретация всегда предполагает динамическое связывание во время выполнения. Динамическое связы- связывание означает, что до выполнения программы типы всех переменных и выражений не известны. JavaScript не поддерживает концепцию классов, а вместо этого в значительной степени основывается на экземплярах. Наиболее существенный недостаток этого — отсутствие наследования. Потому-то JavaScript и от- относится к категории основанных на объектах, но не объектно-ориентированных, языковпрограммирования. Точечная нотация Доступ к свойствам и методам объекта в JavaScript осу- осуществляется в соответствие с точечной нотацией. Эта запись, показанная в следующем синтаксическом при- примере, обеспечивает иерархический способ доступа к свойствам и выполнениям методов. имяобгьекта. иыяСвойства имяОбгьекта. имяМетода (аргументы) К текущему объекту обращаются через специальную переменную this. В объявлении типа объекта (класса) переменная this ссылается на сам объект. Этот объект (текущий объект) является объектом, для которого объявляется метод. В типе объекта, определяющего комплексные числа, метод сложения двух комплексных чисел записывается следующим образом: // сложить х и у и вьщать rz function add(z){ var a ; var b ; var rz; a = this.real + z.getReal(z); b = this.img + z.getlmg(z); rz = new Complex (a,b) ; return rz;
Базовое подмножество языка JavaScript Часть II Оператор, вычисляющий сумму чисел х и у записы- записывается так: x.add(y); В методе add конструкция this.real указывает на свой- свойство real текущего объекта х, в данном случае — x.real. Точно так же this.img указывает на свойство img объек- объекта x.img, которое хранит мнимую часть х. Исследование объектной модели JavaScript JavaScript-объекты — действительно объекты, в том смысле, что они имеют свойства и методы и могут отве- отвечать на события. Однако, как было показано в этой гла- главе, JavaScript не имеет существующей в ООП возможно- возможности наследования. При изучении объектной модели JavaScript необходимо рассматривать ее как раз в этом контексте. Вместо иерархии классов, которая является основой наследования, объектная модель JavaScript - это иерархия контейнеров (см. рис. 9.9). Если вы хоро- хорошо знакомы с объектно-ориентированными языками программирования, такими как Java, C++ или Delphi, то это самое значительное уточнение, о котором необ- необходимо постоянно помнить при разработке программ на JavaScript. Принцип отношения содержания (containershipJsaKnm- чается в том, что один объект содержит другие объекты. На рис. 9.9 отношения между объектом Form и объек- объектом Radio не являются отношениями предка и потомка (или класса и подкласса), это отношения контейнера (со- (содержащего) и содержимого. Иначе говоря, между этими объектами нет родственных связей, поскольку ни один из них не наследуется от другого. В результате один объект не может наследовать свойства и методы друго- другого, поэтому в такой иерархии нельзя разбить объекты на подклассы. РИСУНОК 9.9. Иерархия встроенных JavaScript-объектов. j- 0 location Н-© document : - -0 ancha ! r© applet ; в- j i™ -.Щ button Ш checkbox 0 NaUpload Ш hidden 0 option raria Н . Ш *иЬ«й - m м Я H в% Language ;¦& tov '-Q Funclkm Q Dale 0 Math Отношения содержания в JavaScript Отношения содержания — важный для понимания тер- термин. При разработке JavaScript-сценариев и прикладных программ необходимо не только понимать, как один объект соотносится с другим, но и (для практических целей) знать, каким образом ссылаться на объект. Как упоминалось ранее в главе (при обсуждении точечной нотации), при ссылке на свойства или методы объекта точка используется для обозначения принадлежности. Например, в следующей примере метод write принад- принадлежит объекту Document: document, write ("<М>По небу плавно летел Однако, эту принадлежность можно расширить с целью включения не только свойств и методов данного объекта, но и других объектов, содержащихся в нем. При необходимости возврата имени объекта Button восполь- воспользуйтесь следующей строкой: ButtonName = document . f ormMain. okButton. name г document — заданное по умолчанию имя объекта Document, a formMain — имя объекта Form, который содержит кнопку okButton. При работе с объектами важно знать, когда есть не- необходимость в ссылке на содержащий объект и когда такой необходимости нет. Например, объект Window - по существу, объект самого высокого уровня, с которым можно работать со стороны клиента. Большинство ссы- ссылок на объекты выполняются в пределах их отношений содержания. Предыдущий пример document.write мож- можно записать и по-другому: window, document.write("<Ы>По небу плавно летел **напильник</Ы>") ; Хотя в большинстве случаев ссылку на window мож- можно проигнорировать, она станет необходимой при работе со множеством окон или фреймов. Например, в листинге 9.3 создается объект Window в функции showStats(), за- затем этот объект разрушается в функции closeWindow(). Листинг 9.3. Создание нового окна и запись в него информации. <html> <head> <title> JavaScript Unleashed</title> <script type="text/javascript"> <! — var windowObject function showStatsO { windowObject = window . open ("", "ViewStats", "toolbar=0, width=300, height=50, resizable=l"); windowObject. document.write ( "<Ь2>Вэтом месяце мы перевыполнили план по
Объекты со стороны клиента составлению планов на следующий месяц. Примите поздравления!</h2>") J function closeWindow()( windowObject.close()' 1 // ~> </script> </head> <body OnUnload="closeWindow(>"> Щелкните на следующей кнопке для получения статистики за месяц. <fortn> <input type="button" value="Show Stats" onclicfc="showStats()"> </form> </body> </html> He следует забывать, что объект Window — един- единственный высокоуровневый объект, который можно не указывать в ссылках на другие объекты. Например, для ссылки на HTML-форму необходимо добавить ее роди- родительский объект (Document) для обозначения, на какой объект выполняется ссылка. Если требуется сослаться на первую форму в объекте Document и подсчитать коли- количество элементов в ней, используется следующая коман- команда: var пшп = document. forms [ 0 ] . length ; Даже в случае, когда форма имеет установленный атрибут name, все равно следует добавлять ссылку на родительский объект: var nuift = document. queryForm. length; Свойства Свойства в JavaScript похожи на атрибуты данных объекта. Свойства объекта выражают характеристики и идентификацию данного объекта. В дополнение к опре- определенным характеристикам и идентифицирующим зна- значениям, атрибуты объекта могут также обозначать состо- состояние объекта или роль, которую объект играет в данное время. Ниже показано, как при разработке проекта можно определить тип объекта Project: function Project (members, leader, currentMilestone, time) { this, members = members; this, leader = leader; this . currentMilestone = currentMilestone; this . time = time ; } После этого можно создавать специфическое про- программное обеспечение проекта myProject: Глава 9 var myProject = new Project (memberGroup, "Шариков", "начало", currTime) ; Объект myProject состоит из группы людей, описан- описанных в объекте memberGroup. Руководитель проекта - Шариков, текущий этап — начало (т.к. проект начат не- недавно). Переменные memberGroup и currTime содержат и другие объекты, которые здесь не описаны. Помимо точечной нотации, существуют и другие способы обращения к свойствам объекта. Следующий пример показывает способ доступа к объекту как к мас- массиву: иняОб'ьекта [ "имяСвойства" | А вот доступ через индексацию: имнОбъекта[целочисленкыйИндекс] Последняя методика возвращает атрибут с номером целочисленныйИндекс. Вне объекта не стоит обращаться к атрибутам объекта непосредственно, поскольку это противоречит принци- принципу инкапсуляции. (Обратитесь в раздел "Инкапсуляция" выше в этой главе.) Методы Метод означает определенный сервис, который класс предоставляет другим объектам. В общем случае, мето- методы можно разбить на следующих четыре категории: • Модификатор (modifier). Это метод, который изменя- изменяет состояние объекта. Модификатор изменяет значе- значение одного и более атрибутов данных объекта. Рас- Распространенная функция модификатора — функция set, устанавливающая значение определенного атри- атрибута объекта. • Селектор (selector). Это метод, который ссылается на атрибуты данных объекта, но не осуществляет ника- никаких изменений. Важная функция селектора — функ- функция get, которая возвращает (получает) значение оп- определенного атрибута объекта. ¦• Итератор (iterator). Это метод, который обращается к всем частям объекта, т.е. ко всем атрибутам данных, в некотором определенном порядке. В соответствие со своим названием, итератор выполняет итерации по ат- атрибутам данных объекта. • Конструктор (constructor). Это метод объектного типа, который создает новый объект по шаблону класса. Конструктор инициализирует новый объект определенными значениямиданных,полученнымив области параметров метода. В JavaScript объектные методы — нормальные фун- функции JavaScript. Обращаться к ним можно в соответствие с точечной нотацией:
Базовое подмножества языка JavaScript Часть II имяОб-ьехта.имяфункции (аргументы) Напомним, что HTML-файл содержит раздел <body>, который создает специальный объект Document на JavaScript. Объект Document поддерживает метод write(). При помощи этого метода можно динамически расши- расширять текстовое содержимое HTML-страницы через сце- сценарии JavaScript. Приведенный ниже оператор печата- печатает строку Пример строки: document.write("Пример строки"); При создании новых объектных типов в JavaScript применяется такой шаблон: function ObjectType(instVarl, this.property1 = instVarl; this . property2 = instVar2; this.methodl = function].; this.method2 = function2; instVar2, f b = this.img + z.getlmg rz = new Complex (a,b); return rz; (z) ; // методы для вычитания, умножения и деления // комплексных чисел пока не реализованы Объектный метод add принимает один параметр типа Complex. Сложение двух комплексных чисел х и у вы- выполняется следующим образом: var х = new Complex (a,b) ; var у = new Complex(c,d) ; var z = x.add(y) ; Внутри объявления функции на свойства текущего объекта можно ссылаться через специальный объект this: а = this, real + z.getReal(z) ; События functionl(paraml, param2, . . .){ здесь следует реализация 1 function2(paraml, param2, . . .){ здесь следуем реализация ] Реализация методов объекта приводится позже в объявлении функции по всем правилам для обычных функций JavaScript. Параметрами функции могут быть строки, числа или целые объекты. Следующий фрагмент кода демонстрирует пример определения класса, пред- представляющего комплексные числа: // определение комплексных чисел function Complex(real, img) { this. real = real; this.img = img; this.getReal = getReal; this.getlmg = getlmg; this, add = add; this.subtract = subtract; this.multiply = multiply; this.divide = divide; i II получить вещественную часть function getReal () { return thi s.real; // получить мнимую часть function getlmg () f .return this. img; } II сложить x и у и получить rz function add(z){ var a; var Ь; var rz ; a = this.real + z.getReal (z) Зачастую операторы JavaScript создают или управляют элементами графического пользовательского интерфей- интерфейса, такими как формы или окна. На рис. 9.10 показан простой графический пользовательский интерфейс (GUI). Листинг 9.4 предназначен для создания формы, по- показанной на рис. 9.10. Некоторые части еще не полнос- полностью запрограммированы, поэтому они выдают сообще- сообщение Функция пока не реализована, так что заходите позже. Листинг 9.4. GUI. Простой <html> <head> <title>npraiep GOK/title> <script type="text/javascript"> У/ функция поиска пока не реализована; // выдать соответствующее сообщение function f search (aForm) { alert ("Функция пока не реализована, ^¦так что заходите позже") ; // функция отображения опций пока // не реализована function foptions(aForm) { alert ("функция пока не реализована, '•так что заходите позже") ; } II—> </script> ¦</head> <body> <h3> Поисковая форма </h3> <hr> <form> Най*ги:
Объекты со стороны клиента <input type="text" name="tfield" size=0"> <br> <input type="radio" name="search"> Простой поиск <br> <input type="radio" name="search"> Распдфенный поиск <br> <:input type="button" name="bsearch" уа1ие="Поиок" onclick="fsearch(this.form)"> <input type="button" name="boptions" value=" Дополнительные оипут" onclick="foptions(this.form)"> </body> </html> Поисковая форма Найти ( Л Простой imi г Расширенный поиск РИСУНОК 9.10. Графический пользовательский интерфейс. В контексте GUI событие — это результат определен- определенных пользовательских действий. Событие генерируется тогда, когда пользователь совершает действие. Напри- Например, когда пользователь щелкает на кнопке интерфей- интерфейса, генерируется событие click. Кдругим событиям GUI относятся: щелчок на флажке, выбор строки из списка, двойной щелчок на элементе, открытие или закрытие окна. Наилучший способ управления GUI реализуется с использованиемпрограммирования,управляемогособы- тиями События могут перехватываться (captured) и об- обрабатываться обработчиками событий JavaScript. Допол- Дополнительная информация может быть найдена в главе 14. В общем случае, события не рассматриваются как особенности, относящиеся к ООП, хотя некоторые объек"но-ориентированные языки программирования также поддерживают события. Большинство элементов U1 (экна, кнопки, текстовые поля, флажки) реагиру- реагируют на определенные события. Эти элементы существу- существуют в JavaScript как встроенные объектные типы. Напри- Глава 9 мер, в JavaScript можно создать кнопку, генерирующую событие onClick в результате щелчка на ней: <form> <input type="button" value="Hai»ei меня" onClick="myfunc()"> </form> В этом примере функция myfunc() выполняется, ког- когда пользователь выполняет щелчок на кнопке "Нажми меня". Некоторые встроенные объекты имеют методы, эмулирующие события. Например, в объекте Checkbox определен метод click(), который эмулирует щелчок на флажке. То же самое можно сказать и об объекте Button. Метод эмуляции события не генерирует событие, объяв- объявленное в другом месте для объекта. Если с событием необходимо связать определенное действие, обрабаты- обрабатывать такое событие придется явно. Поскольку обработчики событий разрешены только для НТМ-дескрипторов, все недавно созданные объек- объектные типы обработчиков событий не имеют. Более под- подробную информацию по событиям и обработчикам со- событий в JavaScript можно найти в главе 14. Дополнительная информация об объектах При детальном рассмотрении полной иерархии объек- объектов JavaScript несложно заметить, что большинство объектов являются либо объектами со стороны клиента, либо со стороны сервера, либо же базовыми. В этом раз- разделе книги описаны объекты со стороны клиента и пред- представлены свойства и методы для каждого из них. Главы 10 и 12 посвящены другим типам объектов JavaScript. ПРИМЕЧАНИЕ В дополнение к упомянутым трем типам объектов Microsoft предлагает и ряд собственных языковых рас- расширений для Windows Scripting Host. Эти расширения дают возможность пользователям организовывать до- доступ к файлам, перемещать папки и открывать при- приложения практически так же, как и пакетные файлы (но эти средства мощнее). Расширения Microsoft в книге не рассматриваются. ¦ -¦ ..... Встроенные в JavaScrip функциональные возможно- возможности со стороны клиента всецело зависят от действий, выполнение которых обеспечивают HTML-страницы. Первый набор объектов вообще зависит от вида браузе- браузера и HTML-дескрипторов в нем. На рис. 1> ! ! показан исходный текст HTML для некоторой Web-страницы с помеченными при помощи стрелок объектами JavaScript. Как видно из рисунка, большинство объектов JavaScript — объектные представления дескрипторов HTML. В табл. 9.1 приводится список объектов со сто-
Базовое подмножество языка JavaScript Часть II рОНы клиента и соответствующих им дескрипторов HTML. Document Form II Form — >U nt кии J]t* to ftte a 4at«tl*a picture ci см leOWJ ос Какаса Hat Text Tent Button РИСУНОК 9.11. Очень многие объекты JavaScript соответствуют дескрипторам HTML. Таблица .1. Объекты JavaScript со стороны клиента и соответствующие им дескрипторы HTML. JavaScript-объект Button Checkbox Hidden Fileupload Password Radio Reset Select Листинг 9.5. Доступ Соответствующий HTML-дескриптор < input type: < input type= <input type="hidden": < input type= <inputtype="password"> <input type="radi < input type=" reset" > <select> к свойствам объекта navigator. JavaScript-объект Соответствующий HTML-дескриптор Frame Document Layer Link Image Area Anchor Applet Plugin Form Submit Text Textarea Option <frame> <body> <layer> or <ilayer> <a href=" <img> <map> <a name < applet > <embed> <form> < input type= <input type= <textarea> <option> Во время исследований этих объектов обратите вни- внимание на различные способы, по которым они представ- представляются пользователям и разработчикам. Объект navigator Объект navigator, смело названный так изобретателя- изобретателями JavaScript (Компания Netscape), представляет ис- используемый браузер. С помощью этого объекта можно получить информацию об имени и версии браузера, а также другую дополнительную информацию (см. рис. 9. 12). Объект navigator поддерживается как в Netscape Navigator, так и в Microsoft Internet Explorer. Этот объект имеет еще и два дочерних объекта: Plugin и Mimetype. Код, который был использован для получения ин- информации, показанной на рис. 9.12, При !н в листин- листинге 9.5. Таблица 9.2 содержит список методов и свойств объекта navigator. <html> <head> <title>JavaScript </head> <body> <script language^"JavaScript"> nt.write (" ) + navigator. appCodeName + " ) + navig itor. appName + "<bi document.write ("navigator.appVersii ) + navigator appVersion[srj + "<br> ".bold(> + navigator.language [sr] + "<br>") ; I + navigator 5 + "<br> + navigator.platfo a + "<bi ) + navigator.plugins + " it.write ("navigator ) + navigator . userAgent + " document, closet) ;
Объекты со стороны клиента Глава 9 II—> </script> </body> </html> Таблица 9.2. Методы и свойства объекта navigator. Тип Элемент Описание Функция, проверяющая, поддерживается ли данный браузер Java. Метод в JavaScript 1.1. Перестраивает массив установленных подключаемых модулей. Метод появился в JavaScript 1.2. Позволяет читать и устанавливать пользовательские предпочтения в браузере. Метод появился в JavaScript 1.2. Проверяет, включено ли искажение нежелательных данных. Метод появился в JavaScript 1.1. Представляет кодовое имя браузера. Представляет официальное имя браузера. Выдает информацию о версии браузера. Выдает язык браузера. Свойство появилось в JavaScript 1.2. Ссылается на массив объектов Mimetype, который содержит все поддерживаемые данным браузером типы MIME. Свойство появилось в JavaScript 1.1. Строка, указывающая на платформу, на которой выполняется браузер. Свойство появилось в JavaScript 1.2. Ссылается на массив объектов Plugin, который содержит все подключаемые модули браузера. Свойство появилось в JavaScript 1.1. Строка, содержащая значение заголовка "user-agent". Метод Свойство javaEnabled() появился plugins.refreshQ preference() taintEnabled() appCodeName appName appVersion language mimeTypes platform plugins userAgent p: Netscape navigatorappVcrriom A OS flerj (WinHT, I .Na*) navigator.hiiiiuagu: en navigator.minieTypes: [ubjectMiitieTypeAiray] navifsitor.plarronn: Win32 iviripator.pl» jini: [object Pinguid» MTigator.userAa8nt: МояЛзЛ OS [en] C.VinrTT. I :Mav) .'; I.'::-'- ¦ >¦¦ :¦:¦¦¦¦¦::.¦. РИСУНОК 9.12. Использование объекта navigator для получения информации о браузере Объект Mimetype Объект MIME (multipurpose Internet mail extensions, мно- многоцелевые почтовые расширения II ;t), который яв- является подобъектом объекта navigator, появился в. JavaScript 1.1. Объект позволяет обращаться к информа- информации о MIME-типах, поддерживаемых подключаемыми модулями. Как и объект Plugin, он не поддерживается Internet Explorer. Свойства объекта Mimetype перечисле- перечислены в табл. 9.3. Таблица 9.3. Свойства объекта Mimetype. Свойство Описание description Содержит описание Mimetype. enabledPlugin Содержит подключаемый модуль для определенного Mimetype. suffixes Содержит расширение файла для Mimetype. type Содержит строку, представляющую Mimetype. Объект Plugin Объект Plugin, появившийся в JavaScript J. 1 и не поддер- поддерживаемый Internet Explorer, создается при наличии под- подключаемых модулей, установленных в браузере. Этот объект содержит массив элементов и MIME-типоб об- обрабатываемых подключаемыми модулями. Как показа- показано в табл. 9.4, он имеет только свойства, однако в объек- объекте navigator существует метод pjugins.refresh(), который
Базовое подмножество языка JavaScript Часть II дает возможность повторно построить массив подклю- подключаемых модулей. На рис. 9.13 показан пример того, как можно задействовать этот объект и метод document.writeQ для отображения информации об установленных под- подключаемых модулях. Java ..2.2 for Nei RealPlayci(tm) Livc'-Jwm ф №ms«tnr vid> JDK/.TRE 1.22 mpatm-with JDK/JRE l.Z 2 (DLL Helper) rape Navigator wHh ЛЖЛНЕ 1.12 fl>LL Helper) t-Elrtbledplug In Netscape Navigator Plug-in for Acrobat Shockwave IJash з о г? Siwnd Player to Netscape Navigator, v. | 1,1515 QuickTime 'lug-In tor Win32 v 1 1 и 14 phiaa DLL РИСУНОК 9.13. Отображение установленных подключаемых модулей при помощи объекта Plugin. Таблица 9.4. Свойства объекта Plugin. Свойство Описание description Ссылается на описание подключаемых модулей. filename Ссылается на имя файла подключаемого модуля. length Ссылается на количество MIME-типс содержащихся в массиве. name Ссылается на имя подключаемого модуля. Объект Window Web-браузеры (Netscape Navigator, Microsoft Internet Explorer или любой другой) представляются пользовате- пользователям в окне. Все, что пользователь делает с браузером, выполняется в пределах этого окна. Кроме того, каждый экранный элемент также содержится внутри этого окна. Таблица 9.5. Свойства и методы объекта Window. Объект Window использует прямое значение этой метафоры (см. рис. 9.14). Он считается самым главным объектом в иерархии объектов со стороны клиента в JavaScript и содержит все другие клиентские объекты {кроме собственно объекта navigator). Точно так же, как можно открывать множество окон в браузере, в коде можно работать сразу со многими объектами Window. Кнопка Текст Ссылка РИСУНОК 9.14. Объект Window содержит все )ругие элементы — как визуально, так и в коде. Объект Window не имеет эквивалентного дескрипто- дескриптора HTML, тем не менее, он создается при открытии нового окна браузера. Следующий пример показывает, как работать с объектом Window в коде JavaScript. Пред- Предположим, что требуется добавить текст в строку состоя- состояния окна: window.status = 'Добро пожаловать на мою домапшюю страницу' ' ; Подобно другим объектам, Window имеет несколько различных свойств и методов. Поскольку Window — это объект самого верхнего уровня, некоторые из объектов могут вызываться или упоминаться без window, перед ними. Пример — метод alert(). В табл. 9.5 перечислены все методы и свойства объекта Window. Тип Элемент Описание Метод atob() alertO back() blur() Декодирование строки, закодированной с помощью кода base 64. Метод появился в JavaScript 1.2. Выводит диалоговое окно предупреждения, отображающее переданную в метод текстовую строку. Загружает предыдущую страницу вместо экземпляра window. Метод появился в JavaScript 1.2. Убирает фокус из окна.
Объекты со стороны клиента Глава 9 Элемент Описание btob() captureEvents() clearlnterval() clearTimeout() close() confirm() crypto. random() crypto.signText() disableExternalCapture() enableExtemalCapture() find() focus() forward () handleEvent() ihome() moveByf) moveToQ open{) ,print() prompt() releaseEvents() resize By(). resizeTo() route Event() scrollByO scrollToQ setHotKeys() setlnterval() setResizableQ Кодирует строку с использованием кода base 64. Метод появился в JavaScript 1.2. Заставляет окно перехватывать все события указанного типа. Метод появился в JavaScript 1.2. Обнуляет интервал, установленный методом setlntervalQ. Метод появился в JavaScript 1.2. Удаляет тайм-аут, установленный методом setTimeout(). Закрывает экземпляр окна. Метод появился в JavaScript 1.1. Отображает диалоговое окно подтверждения. Генерирует случайную строку данных заданной длины. Метод появился в JavaScript 1.2. Возвращает строку закодированных данных, которая представляет указанный объект. Метод появился в JavaScript 1.2. Запрещает внешний перехват событий. Метод появился в JavaScript 1.2. Разрешает внешний перехват событий для страниц, загруженных с других серверов. Метод появился в JavaScript 1.2. Отображает диалоговое окно поиска, в которое можно вводить текст для поиска на текущей странице. Метод появился в JavaScript 1.2. Устанавливает фокус на указанное окно. Метод появился в JavaScript 1.1. Загружает следующую страницу вместо экземпляра window. Метод появился в JavaScript 1.2. Вызывает обработчик для передаваемого события. Метод появился в JavaScript 1.2. Загружает определенную пользователем страницу в экземпляр window. Метод появился в JavaScript 1.2. Перемещает окно в соответствие с заданным смещением. Метод появился в JavaScript 1.2. Перемещает окно в заданную позицию. Метод появился в JavaScript 1.2. Открывает новый экземпляр окна. Вызывает диалоговое окно печати, позволяющее вывести на печать текущее окно. Метод появился в JavaScript 1.2. Отображает диалоговое окно приглашения на ввод команды. Освобождает захваченные события указанного типа. Метод появился в JavaScript 1.2. 'Изменяет размеры окна в соответствие с указанным смещением. Метод появился в JavaScript 1.2. Изменяет размеры окна до указанных. Метод появился в JavaScript 1.2. Передает события указанного типа на обработку собственными средствами. Метод появился в JavaScript 1.2. Выполняет прокрутку документа в окне к указанной позиции. Метод появился в JavaScript 1.1. Выполняет прокрутку документа в окне в соответствие с заданным смещением. Метод появился в JavaScript 1.2. Выполняет прокрутку документа к указанной позиции в окне. Метод появился в JavaScript 1.2. Назначает или отменяет назначение комбинаций клавиш окна в случае отсутствия меню. Метод появился в JavaScript 1.2. Вызывает функцию или вычисляет выражение каждый раз по прошествии определенного числа миллисекунд. Метод появился в JavaScript 1.2. Определять, может ли пользователь изменять размеры окна. Метод появился в JavaScript 1.2.
Базовое подмножество языка JavaScript Часть II Тип Элемент Описание setTimeout() setZOptionsQ stop() Свойство closed crypto defaultStatus document frames history innerHeight «nnerWidth length location locationbar locationbar.visible menubar menubar.visible name offscreenBuffering opener outerHeight outerWidth pageXOffset pageYOffset parent personal bar personalbar. visible screenX screenY scrollbars scrollbars.visible Вызывает функцию или выполняет выражение по прошествии определенного числа миллисекунд. Позволяет определять z-порядок расположения элементов в окне. Метод появился в JavaScript 1.2. Останавливает загрузку элементов в текущем окне. Метод появился в JavaScript 1.2. Определяет, был ли экземпляр window закрыт. Обеспечивает доступ к возможностям кодирования Navigator. Свойство появилось в JavaScript 1.2. Определяет заданное по умолчанию сообщение в строке состояния окна. Ссылается на всю информацию относительно документа, находящемся в данном окне. Обратитесь к описанию объекта Document для получения дополнительной информации. Ссылается на всю информацию относительно фреймов данного окна. Обратитесь к описанию объекта Frame для получения дополнительной информации. Ссылается на URL-адреса, которые посетил данный пользователь. Свойство появилось в JavaScript 1.1. Содержит высоту в точках области отображения, занятой текущим окном. Свойство появилось в JavaScript 1.2. Содержит ширину в точках области отображения, занятой текущим окном. Свойство появилось в JavaScript 1.2. Определяет количество фреймов в текущем окне. Содержит текущий URL страницы, загруженной в окно. Ссылается на окно адреса в браузере. Свойство появилось в JavaScript 1.2 Содержит логическое значение, которое сообщает, видно ли пользователю окно адреса браузера. Свойство появилось в JavaScript 1.2. Ссылается на меню браузера. Свойство появилось в JavaScript 1.2. Содержит логическое значение, которое сообщает, видно ли пользователю меню браузера. Свойство появилось в JavaScript 1.2. Содержит имя окна. Содержит логическое значение, которое позволяет определять, выполнялось ли обновление окна в экранном буфере. Свойство появилось в JavaScript 1.2. Содержит имя окна, из которого было открыто вторичное окно. Содержит высоту в точках внешней области текущего окна. Свойство появилось в JavaScript 1.2. Содержит ширину в точках внешней области текущего окна. Свойство появилось в JavaScript 1.2. Содержит координату х текущего окна. Свойство появилось в JavaScript 1.2. Содержит координату у текущего окна. Свойство появилось в JavaScript 1.2. Ссылается на родительское окно, которое отображает текущий фрейм. Ссылается на полосу Personal браузера. Свойство появилось в JavaScript 1.2. Содержит логическое значение, которое сообщает, видна ли пользователю полоса Personal браузера. Свойство появилось в JavaScript 1.2. Ссылается на координату х на левого верхнего угла окна браузера. Свойство появилось в JavaScript 1.2. Ссылается на координату у на левого верхнего угла окна браузера. Свойство появилось в JavaScript 1.2. Ссылается на полосы прокрутки браузера. Свойство появилось в JavaScript 1.2. Содержит логическое значение, которое сообщает, видна ли пользователю полосы прокрутки. Свойство появилось в JavaScript 1.2.
Объекты со стороны клиента Тип Элемент1 Глава 9 Описание self status statusbar statusbar.visible toolbar toolbar.visible top window Ссылается на текущее окно. Ссылается на сообщение, отображаемое в строке состояния окна. Ссылается на строку состояния браузера. Свойство появилось в JavaScript 1.2. Содержит логическое значение, которое сообщает, видна ли пользователю строка состояния браузера. Свойство появилось в JavaScript 1.2. Ссылается на панель инструментов браузера. Свойство появилось в JavaScript 1.2. Содержит логическое значение, которое сообщает, видна ли пользователю панель инструментов браузера. Свойство появилось в JavaScript 1.2. Ссылается на родительское окно, отображающее текущий фрейм. Ссылается на текущее окно. Объекты верхнего уровня Объект верхнего уровня со стороны клиента Window содержит четыре дочерних объекта. Эти объекты явля- являются основой для всех других объектов, с которыми при- придется сталкиваться при программировании на JavaScript. Очень важно хорошо знать и сами объекты, и способы их совместного функционирования. Список объектов выглядит так: Document • Frame • History Location Объект Document Несмотря на то что объект Window является объектом верхнего уровня в иерархии, Document, возможно, - один из наиболее важных. Объект Document, показан- показанный на рис. 9.15, ответственен за все фактическое содер- содержимое, отображаемое на данной странице. При исполь- Таблица 9.6. Методы и свойства объекта Document. зовании объекта Document появляется возможность ото- отображать динамические HTML-страницы. Все, что содер- содержится в документе — это типовые элементы пользова- пользовательского интерфейса Web-приложения. В табл. 9.6 перечислены методы и свойства объекта Document. Text Checkbox- . tt.tv, 'с* it* Information Survey Li ЕЬгШ&ол 4ut ш!ш.1Ьи ш Kn Г 5-10 hoius Г 10-20 burs с Ыме tt РИСУНОК 9.15. Объект Document отвечает за содержимое страницы. Тип Элемент Описание Методы Захватывает события, которые будут обрабатываться документом. Метод появился в JavaScript 1.2. close() Закрывает поток вывода документа. Позволяет выборочно применять стиль к HTML-элементу, который появляется в определенном контексте. Метод появился в JavaScript 1.2. getSelection() Возвращает выделенный текст. Метод появился в JavaScript 1.2. Вызывает обработчик для указанного события. Метод появился в JavaScript 1.2. ореп() Открывает поток вывода документа. releaseEvents() Освобождает события, захваченные документом. Метод появился в JavaScript 1.2. routeEvent() Перенаправляет перехваченные события к другим объектам. Метод появился в JavaScript 1.2. write() Добавляет текст к документу.
Базовое подмножество языка JavaScript Часть II Элемент Описание writeln() Добавляет к документу текст и символ новой строки. Свойства alinkColor Цвет активной ссылки. all Массив всех HTML-дескрипторов документа. Метод появился в Jscript 3.0. anchors Массив объектов Anchor. Свойство появилось в JavaScript 1.2. applets Массив объектов Applet. Свойство появилось в JavaScript 1.1. bgcolor Цвет фона документа. classes Массив классов таблиц стилей. Свойство появилось в JavaScript 1.2. cookie cookie-набор, связанный с документом. domain Домен документа. Свойство появилось в JavaScript 1.1. embeds Массив встроенных объектов. Свойство появилось в JavaScript 1.1. fgcolor Цвет текста в документе. forms Массив объектов Form. formName Определяет экземпляр Form, к которому обращаются с использованием атрибута name в дескрипторе <form>. Свойство появилось в JavaScript 1.1. height Определяет высоту документа в точках. Свойство появилось в JavaScript 1.2. ids Массив идентификаторов таблиц стилей. Свойство появилось в JavaScript 1.2. images Массив объектов Image. Свойство появилось в JavaScript 1.2. lastModified Дата последней модификации документа. layers Массив объектов Layer. Свойство появилось в JavaScript 1.2. linkColor Цвет ссылок. links Массив объектов Link. plugins Массив подключаемых модулей. Свойство появилось в JavaScript 1.1. referrer URL документа, с которым был связан текущий документ. tags Массив дескрипторов таблиц стилей. Свойство появилось в JavaScript 1.2. title Заголовок документа. URL URL текущего документа. Свойство появилось в JavaScript 1.1. vlinkColor Цвет посещенных ссылок. width Определяет ширину документа в точках. Свойство появилось в JavaScript 1.2. ПРИМЕЧАНИЕ Ж-!1' I Многие из перечисленных выше свойств обладают под- свойствами и подмечодами. Для получения дополни- дополнительной информации обратитесь в документацию Netscape (http://developer.netscape.com) или Microsoft (http://msdn.microsoft.com). Чаще всего объект Document используется для гене- генерации HTML-страниц при помощи JavaScript. Для упо- упомянутых целей можно применять методы document.write() или document.writeln(). Например, приведенный ниже код отображает HTML-текст, переданный в качестве параметра: <html> <body> <script type="text/javascript"> document. wri te ( "<Ы>Текс», i«JavaScript</hl>") ; </soript> созданный </body> </html> Объект Frame Как будет показано далее в книге, фреймы — очень важ- важные объекты, предназначенные для совершенствования внешнего вида Web-приложения. Объект Frame пред- представляет собой рамку в наборе рамок. В многофреймо- многофреймовом представлении объект Window — это страница, ко- которая содержит определение <frameset>. В табл. 9.7 перечислены методы и свойства объекта Frame. Объект History Еще одна возможность браузера связана с отслеживани- отслеживанием перечня сайтов, которые посетил пользователь во время данного сеанса. Эта особенность известна как спи- список хронологии (history list), или список посещений сайтов; эквивалентом упомянутого списка в JavaScript является объект History.
Объекты со стороны клиента Глава 9 Таблица 9.7. Методы и свойства объекта Frame. Тип Элемент Описание Убирает фокус из данного фрейма. Метод появился в JavaScript 1.1. Отменяет повторное выполнение. Метод появился в JavaScript 1.2. Отменяет любое отложенное выполнение. Устанавливает фокус на фрейм. Метод появился в JavaScript 1.1. Вызывает диалоговое окно Print. Метод появился в JavaScript 1.2. Планирует функцию для повторного выполнения. Метод появился в JavaScript 1.2. Устанавливает список функций для отложенного выполнения. Текущий документ, загруженный в фрейм. Массив, содержащий ссылки на дочерние фреймы. Длина массива фреймов. Атрибут name дескриптора <frame>. Главное окно или фрейм, из которого создаются дочерние фреймы. Ссылка на текущий фрейм. Окно браузера, которое выполняет сценарий. Ссылка на текущее окно или фрейм. Метод Свойство blurQ clearlntervalQ clearTimeoutQ focus() print() setlnterval() setTimeout() document frames length name parent self top window Предположим, необходимо обеспечить, чтобы пос- после щелчка на кнопке выполнился возврат на две стра- страницы назад в списке хронологии. Обработчик событий для этой кнопки должен вызывать функцию, текст ко- которой приводится ниже. Все методы и свойства этого объекта сведены в табл. 9.8. < script type=" text/ javascript "> function goBaekTwoPages () { window.history.go(-2); II—> </script> Объект Location World Wide Web дает представление обо всем. Каждый объект Window предназначен для передачи содержимо- содержимого пользователю, однако это содержимое должно отку- откуда-то исходить. Местонахождение Web-страницы содер- содержится в объекте Location. Этот объект используется для хранения всей информации об URL для данного окна. Таблица 9.8. Методы и свойства объекта History. Хотя пользователи видят информацию об URL на эк- экране в окне адреса (см. рис. 9.16), с этой же информа- информацией можно работать и через объект Location. Если из текущего URL требуется выделить часть, касающуюся протокола, воспользуйтесь таким кодом: < soript type="text/javascript"> < ! — function evalProtocol() { ¦curProtocol = window.location.protocol; if (curProtocol = "http:"){ alert("Документ был загружен из Web."); }else{ if (curProtocol = "?ile:"){ alert("Документ был загружен из ^локального жесткого диска. ") ; >else{ alert("Документ был загружен *¦* откуда-то еще.") ; j > II—> </script> Методы и свойства этого объекта перечислены в табл. 9.9. Тип Элемент Описание Загружает предыдущий URL в списке хронологии. Загружает следующий URL в списке хронологии. Загружает URL из списка хронологии, расположенный по указанному смещению. Ссылается на текущий URL в списке хронологии. Свойство появилось в JavaScript 1.1. Возвращает количество элементов в списке хронологии. Ссылается на следующий URL в списке хронологии. Свойство появилось в JavaScript 1.1. Ссылается на предьиущий URL в списке хронологии. Свойство появилось в JavaScript 1.1. Метод Свойство back() forward () ДО() current length next previous
Базовое подмножество языка JavaScript Часть II Таблица 9.9. Методы и свойства объекта Location. Тип Элемент Описание Метод, Свойство reloadQ replace() hash host ihostname href pathname port protocol search Перезагружает текущий URL в окне браузера. Метод появился в JavaScript 1.1. Загружает новую страницу вместо текущей. Метод появился в JavaScript I Представляет имя привязки в URL, которое начинается с символа "; Представляет имя хоста и номер порта, указанные в URL. Представляет имя хоста, указанное в URL. Представляет полный URL. Представляет часть PATHJNFO из URL. Представляет номер порта, указанный в URL. Представляет протокол, указанный в URL. Часть URL, касающаяся поиска, включая символ ?. Адрес \VeIcometo Acadia Software tioniwe ;cal5 Ъо'блу must w>tlr will teycuitlie T.txl point rrieaso. vAij we '^ml tecbnolasr^ftoJjywwsllas aaAJaraScfipt. but sea РИСУНОК 9.16. Пользователи работают с окном адреса, но можно работать и с объектом Location. Объекты второго уровня Точно так же как объект Window имеет подобъекты, объекты второго уровня существуют и в Document. Ниже эти объекты рассматриваются более подробно. ОбъектAnchor Объект Anchor соответствует тексту или изображению на HTML-странице, на которые можно ссылаться через гипертекстовую ссылку. На практике этот объект ис- используется редко, посему он — наименее важный из всех объектов со стороны клиента. В табл. 9.10 содержится список свойств этого объекта. Объект Area Объект Area, который стал доступен в JavaScript 1.1, позволяет определять на изображении область, которая будет рассматриваться в качестве карты изображения. То, что задано атрибутом href дескриптора <агеа> будет заг- загружаться в окно после щелчка мышью на определенной области изображения. Таблица 9.11 содержит свойства и методы этого объекта. Таблица 9.10. Свойства объекта Anchor. Свойство Описание name Имя, обеспечивающее доступ к привязке из ссылки. text Текст, который появляется между дескрипторами <а> и </а>. х Координата х привязки, у Координата у привязки. Объект Applet Объект Applet, впервые введенный в JavaScript I. I, пред- представляет собой JavaScript-эквивалент HTML-дескрипто- HTML-дескриптора <applet>. В общем смысле подобные JavaS ты не имеют собственных методов, но это явное несоответствие, поскольку из JavaScript можно обра- обращаться к определенным методам конкретного Java-an- лета. Поэтому свойствами объекта Applet являются все общедоступные поля Java-аплета, а методами — все об- общедоступные методы. Объект Form Забудьте ненадолго о таких надстройках, как Java-апле- ты или элементы управления ActiveX, которые могут вза- взаимодействовать с пользователем. Если мыслить только в терминах HTML-мира, единственный способ взаимо- взаимодействий с пользователем — через форму и ее элементы (см. рис. 9.17). Формы оживляют статические страницы, обеспечивая возможность пользователям взаимодейство- взаимодействовать с интерфейсом через элементы управления. На форму можно помещать кнопки, текст и другие интер- интерфейсные элементы. Объект Form представляет собой сред- средство взаимодействия в сценариях с HTML-элементами. В табл. 9.12 перечислены методы и свойства объекта Form.
Таблица Тип- 9. 11. Методы ¦Элемент и свойства объекта Area. Описание Объекты со стороны клиента Глава 9 ЕШ Метод Вызывает соответствующий обработчик данного события. Метод появился в JavaScript 1.2. hash Часть URL, которая является привязкой, включая и символ #. host Имя хоста (IP-адрес) и порт, указанные в URL. hostname Имя хоста, указанное в URL href Полный URL pathname Путь для файла, указанного в URL, начиная с символа /. port Порт, указанный в URL. protocol Протокол, указанный в URL, включая завершающее двоеточие (:). search Часть URL, касающаяся поиска, включая начальный вопросительный знак (?). target Имя выходного окна, в котором должен отображаться URL. text Текст, который встречается между дескрипторами <агеа> и </агеа>. х Координата х области. у Координата у области. Таблица 9.12. Методы и свойства объекта Form. Тип Элемент- Описание Метод Вызывает соответствующий обработчик событий. Метод появился в JavaScript 1.2. reset() Устанавливает для элементов формы их значения по умолчанию. Метод появился в JavaScript 1.1. Генерирует событие submit, которое приведет к отправке браузером данных в серверную программу, указанную в атрибуте action дескриптора <form>. Свойство action Содержит атрибут action экземпляра <form>. elements Массиз, содержащий все элементы <form>. encoding Содержит атрибут enctype экземпляра <form>. length Количество элементов, содержащихся в форме, method Содержит атрибут method экземпляра <form>. name Содержит атрибут name экземпляра <form>. target Содержит атрибут target экземпляра <form>. Объект Image Объект Image является инкапсуляцией HTML-изображе- HTML-изображения. Возможно, наиболее эффективное использование этого объектного типа заключается в Квитировании изоб- изображений, предназначенных для отображения на экране. Для этого потребуется создать объект Image и загрузить в него с сервера данные изображения до того, как их потребуется отобразить в браузере. Как только возник- возникнет потребность в изображении, то вытолкнуть его из кеша окажется гораздо быстрее, нежели загрузить из сервера. В табл. 9.13 приведены методы и свойства объекта Image. РИСУНОК 9.17. Формы помогают создавать интерактивные HTML страницы.
Базовое подмножество языка JavaScript Часть II Таблица 9.13. Методы и свойства объекта Image. Тип Элемент Описание Вызывает обработчик для указанного события. Метод появился в JavaScript 1.2. Ширина границы изображения. Сообщает, завершена ли загрузка изображения. Высота изображения. Отступ от левого и правого краев изображения. Альтернативное изображение для мониторов с низким разрешением. Имя изображения. URL изображения. Отступ от верхнего и нижнего краев изображения. Ширина изображения. Метод Свойство handleEvent() border complete Iheight hspace lowsrc name src vspace width Объект Layer Объект Layer, появившийся в JavaScript 1.2 и поддержи- поддерживаемый только браузерами Navigator, позволяет JavaScript Таблица 9.14. Методы и свойства объекта Layer. работать со слоями (layers) документа. Для получения исчерпывающей информации о слоях обратитесь в часть III книги. Таблица 9.14 содержит список методов и свойств объекта Layer. Тип Элемент Описание Метод Свойство captureEvents() handleEventO load() moveAbovef) moveBelowQ moveByO moveToQ moveToAbso!ute() releaseEvents() resize By () resizeTo() routeEvent() above background below bgColor clip.bottom clip.height clip.left clip.right clip.top clip.width document left name Определяет типы событий для захвата. Вызывает обработчик для указанного события. Загружает новый URL. Перемещает слой поверх другого слоя. Перемещает слой под низ другого слоя. Перемещает слой в указанную позицию. Перемещает верхний левый угол окна к указанным экранным координатам. Изменяет позицию слоя в соответствие с указанными в точках координатами в пределах страницы. Освобождает захваченные события указанного типа. Изменяет размеры слоя на заданные значения высоты и ширины. Приводит размеры слоя к заданным значениям высоты и ширины. Передает перехваченное событие далее по нормальной иерархии событий. Определяет слой выше данного. Ссылается на фоновое изображение слоя. Определяет слой ниже данного. Ссылается на цвет фона слоя. Ссылается на нижнюю границу области отсечения слоя. Ссылается на верхнюю границу области отсечения слоя. Ссылается на левую границу области отсечения слоя. Ссылается на правую границу области отсечения слоя. Ссылается на вершину области отсечения слоя. Ссылается на ширину области отсечения слоя. Ссылается на объект Document, который содержит данный слой. Ссылается на координату х слоя. Ссылается на имя слоя.
Объекты со стороны клиента Тип Элемент Глава 9 Описание радеХ Ссылается на координату х левой границы окна документа. pageY Ссылается на координату у левой границы окна документа. parentLayer Ссылается на родительский слой. siblingAbove Ссылается на слой, находящийся выше zlndex. siblingBelow Ссылается на слой, находящийся ниже zlndex. src Ссылается на URL с исходным кодом слоя. top Ссылается на координату у слоя. visibility Ссылается на состояние видимости слоя. window Ссылается на объект Window или Frame, который содержит данный слой. х Ссылается на координату х слоя. у Ссылается на координату у слоя. zlndex Ссылается на расположение этого слоя относительно других слоев в z-порядке. Объект Link Вспомните, что World Wide Web ("всемирная паутина") была разработана в 1989 г. с целью обеспечения простых гипертекстовых связей HTML-страниц. Возможно, из- за всеобщего увлечения Web-приложениями ссылка ос- остается основой Web-технологии. Объект Link позволяет работать с ссылками в JavaScript-коде. Поскольку ссыл- ссылка — это просто путь к другой HTML-странице или сай- сайту, объект Link очень похож на объект Location (кото- (который содержит ту же самую информацию, но для текущей Таблица 9.15. Методы и свойства объекта Link. HTML-страницы). Методы и свойства этого объекта собраны воедино в табл. 9.15. Объект Plugin Подобно объекту Applet, объект Plugin — это способ получения доступа ко всем подключаемым модулям, установленным в браузере в текущий момент. Обрати- Обратите внимание, что этот объект, впервые введенный в JavaScript 1.1, в Internet Explorer не поддерживается. В табл. 9.16 перечислены свойства этого объекта. Тип Элемент Описание Вызывает обработчик для указанного события. Метод появился в JavaScript 1 .2. Представляет имя привязки в URL для ссылки, начинающееся с символа #. Представляет часть URL ссылки, касающуюся хоста. Представляет часть URL ссылки, касающуюся имени хоста. Представляет полный URL ссылки. Представляет часть URL ссылки, относящуюся к имени пути. Представляет часть URL-ссылки, относящуюся к порту. Определяет часть URL ссылки, относящуюся к протоколу. Представляет часть URL-ссылки, относящуюся к запросу. Представляет имя объекта Window, отображающего ссылку. Текст ссылки. Свойство появилось в JavaScript 1.2. Ссылается на координату х ссылки. Ссылается на координату у ссылки. Таблица 9.16. Свойства объекта Plugin. Метод Свойство handletventO hash host hostname href pathname port protocol search target text. Свойство Описание description Содержит описание подключаемого модуля. filename Содержит имя файла подключаемого модуля. length Содержит количество типов MIME, поддерживаемых подключаемым модулем. name Содержит имя подключаемого модуля.
Базовое подмножество языка JavaScript Часть II Объекты третьего уровня Следующий уровень JavaScript-объектов со стороны клиента — объекты третьего уровня. Все эти объекты являются подобъектами объекта Form. Они вложены в объект Form по тому же способу, по которому элемен- элементы HTML вкладываются между парой дескрипторов <form>. Объект Button Если только вы не перешли к Web-разработке от сим- символьно-ориентированных сред, вы несомненно знакомы с кнопками. JavaScript содержит три "кнопочных" объек- объекта: Button, Submit и Reset. Каждый из них реально пред- представляется с помощью HTML-дескрипторов. Объект Button — универсальная кнопка, к которой необходимо добавлять используемый код, в то время как две другие предназначены для строго определенных це- целей. Однако, объект Button возможно использовать в той же роли, что и объекты Submit (вызывая Form.submit()) или Reset (вызывая Form.reset()). Таблица 9.17 содержит методы и свойства объекта Button. :.. СОВЕТ ..? а :• ¦ ¦ . ¦¦ .- ...'¦¦¦ _ ' ,=¦ Ширина кнопки определяется длиной текста, передава- передаваемого через параметр value. Для увеличения ширины кнопки следует добавить пустое место вокруг текста: <1NPUT type=button value=" OK " onClick="doThis()"> Объект Checkbox Другой распространенный элемент управления в стан- стандартном пользовательском интерфейсе — это флажок. Упомянутый элемент позволяет задавать значения yes/ по или true/false, выполняя щелчок на флажке. В табл. 9.18 перечислены свойства и методы объекта Checkbox. Объект FileUpload Объект FileUpload, впервые появившийся в JavaScript 1.1, представляет собой эквивалент HTML-элемента, ре- реализующего загрузку файла. Очень немногие действия можно выполнить с этим объектом в JavaScript — мож- можно только сослаться на его свойства. Объект FileUpload не содержит реальных методов. В табл. 9.19 перечисле- перечислены свойства объекта FileUpload. Объект Hidden Еще один объект типа поля — Hidden; он подобен тек- текстовому объекту с установленным в false свойством visible. Этот объект используется для сохранения значе- значений с целью передачи их серверному процессу. Объект Hidden происходит из тех времен, когда HTML суще- существовал без JavaScript, когда не было таких вещей, как переменные, массивы и объекты, предназначенных для хранения значений. Хотя этот объект все еще можно применять для передачи данных между страницами в многостраничных приложениях, многие из полей дан- данных объекта Hidden в JavaScript уже не нужны. В табл. 9.20 сведены свойства объекта Hidden. Объект Password Если бы в JavaScript поддерживался механизм наследо- наследования, объект Password был бы подклассом объекта Text. Единственное различие между этими двумя объектами — так это то, что любые символы, введенные в объект Password, отображаются звездочками вместо своих ре- реальных значений. В табл. 9.21 перечислены методы и свойства объекта Password. Объект Radio Переключатели представляют собой взаимоисключаю- взаимоисключающие элементы управления, т.е. если один переключатель выбран, все другие переключатели в том же наборе ста- становятся невыбранными. Объект Radio обеспечивает пе- переключатель, используемый в HTML-формах. Разработ- Разработчик определяет набор переключателей, устанавливая одно и то же значение их свойства name. Таблица 9.22 содержит свойства и методы объекта Radio. Таблица 9.17. Методы и свойства объекта Button. Тип Элемент Описание Убирает фокус из кнопки. Метод появился в JavaScript 1.1. Вызывает событие click для данной кнопки. Устанавливает фокус на кнопку. Метод появился в JavaScript 1.1. Передает событие соответствующему обработчику, связанному с кнопкой. Метод появился в JavaScript 1.2. Возвращает объект Form, которому принадлежит данная кнопка. Возвращает строку, которая определена в атрибуте name HTML-дескриптора <input>. Возвращает строку, которая определена в атрибуте type HTML-дескриптора <input>. Для объекта Button эта строка — всегда button. Свойство появилось в JavaScript 1.1. Возвращает строку, которая выводится в графическом представлении кнопки. Метод Свойство Ыиг(> click() focus() handleEventQ form name type value
Таблица Тип 9. 18. Методы Элемент и свойства объекта Описание Checkbox. иоъекты со стороны клиента ШКЕМ Глава 9 1Ш Метод blur() Убирает фокус из флажка. Метод появился в JavaScript 1.1. click() Вызывает обработчик событий onClick. Метод появился в JavaScript 1,1. focusQ Устанавливает фокус в данный флажок. handleEvent() Передает событие соответствующему обработчику событий, связанному с флажком. Метод появился в JavaScript 1.2. Свойство checked Возвращает логическое значение, которое определяет, установлен ли флажок. defaultChecked Возвращает логическое значение, которое содержит начальное состояние флажка. Это значение устанавливается"через атрибут checked. form Возвращает объект Form, которому принадлежит флажок. name Возвращает строку, которая определена в атрибуте name HTML-дескриптора <input>. type Возвращает строку, которая определена в атрибуте type HTML-дескриптора <input>. Для объекта Checkbox эта строка — всегда checkbox. Свойство появилось в JavaScript 1.1. value Возвращает значение, переданное при отправке формы. Таблица 9.19. Методы и свойства объекта FileUpload. Тип Элемент Описание Метод Ыиг() Убирает фокус из окна FileUpload. focus() Устанавливает фокус на окно FileUpload. handleEvent() Вызывает заданный по умолчанию обработчик для указанного события. Метод появился в JavaScript 1.2. select() Выбирает область ввода в окне FileUpload. Свойство name Содержит значение атрибута name для окна FileUpload. form Ссылается на объект Form, содержащий FileUpload. type Содержит значение атрибута type для FileUpload. value Строка, определяющая путь к выбранному файлу. Таблица 9.20. Свойства объекта Hidden. Свойство Описание form Определяет форму, содержащую объект Hidden. name Содержит имя объекта Hidden. type Содержит значение атрибута type объекта Hidden. Свойство появилось в JavaScript 1.1. value Содержит значение атрибута value объекта Hidden. Таблица 9.21. Методы и свойства объекта Password. Тип Элемент Описание Метод Свойство blur() focus() IhandleEventO select() defaultValue form name Убирает фокус из окна Password. Устанавливает фокус на окно Password. Вызывает заданный по умолчанию обработчик для указанного события. Метод появился в JavaScript 1.2. Выделяет текст, введенный в окно Password. Ссылается на атрибут value окна Password. Ссылается на форму, которая содержит окно Password. Ссылается на атрибут name окна Password.
Базовое подмножество языка JavaScript Часть II Элемент Описание туре value Ссылается на атрибут type окна Password. Свойство появилось в JavaScript 1.1. Ссылается на текущее содержание окна Password. Таблица 9.22. Методы и свойства объекта Radio. Тип Элемент Описание Метод Ыиг() Удаляет фокус из объекта Radio. clickQ Моделирует щелчок мыши на переключателе. focusO Устанавливает фокус на переключатель. handleEvent() Вызывает заданный по умолчанию обработчик для указанного события. Метод появился в JavaScript 1.2. Свойство checked Определяет, выбран ли переключатель. defaultChecked Ссылается на атрибут checked HTML-дескриптора <input>. form Ссылается на объект Form, который содержит объект Radio, name Ссылается на атрибут name HTML-дескриптора <input>. type Ссылается на атрибут type HTML-дескриптора <input>. value Ссылается на атрибут value HTML-дескриптора <input>. ПРИМЕЧАНИЕ ¦¦¦' '"" ~"'~~ :. Переключатели группируются на основе общего свой- свойства name. Объект Reset Второй вид связанного с кнопками объекта — объект Reset, впервые введенный в JavaScript 1.2. В результате щелчка объект инициирует событие, которое обеспечи- обеспечивает установку всех элементов формы в их первоначаль- первоначальные значения. Таблица 9.23 содержит список методов и свойств этого объекта. Объект Submit Последний связанный с кнопкой объект — это Submit. В результате щелчка этот объект генерирует событие, передающее все значения формы в программу, опрсде- Таблица 9.23. Методы и свойства объекта Reset. ляемую атрибутом action дескриптора <form>. В табл. 9.24 приведен список методов и свойств этого объекта. Объект Select Существуют и другие стандартные элементы управления оконных сред — выпадающий список и список выбора, которые позволяют пользователю выбирать значения из заранее определенного списка. Отличие между ними состоит в том, что в выпадающем списке пользователь может выбирать только одно значение, в то время как в списка выбора — сразу несколько значений. Поведение обоих упомянутых интерфейсных элементов инкапсули- инкапсулирует объект Select. Другими словами, Select может выс- выступать как выпадающий список (значение по умолча- умолчанию) или как список выбора (если его свойстве multiple установлено в true). Таблица 9.25 содержит свойства и методы объекта Select. Тип Элемент Описание Удаляет фокус из кнопки. Моделирует щелчок мыши на кнопке. Устанавливает фокус на кнопку. Передает событие соответствующему обработчику событий, связанному с кнопкой. Метод появился в JavaScript 1.2. Возвращает объект Form, содержащий данную кнопку. Содержит атрибут name кнопки. Содержит атрибут type кнопки. Содержит атрибут value кнопки. Метод Свойство Ыиг() ¦ciickQ focus() ihandleEvent() form name type value
Объекты со стороны клиента Глава 9 Таблица 9.24. Методы И свойства объекта Submit. Тип Элемент Описание Метод. Свойство lblur() click() focus() ihandleEventQ form name type value Удаляет фокус из кнопки Submit. Метод появился в JavaScript 1.1. Моделирует щелчок мыши на кнопке. Устанавливает фокус на кнопку Submit. Метод появился в JavaScript 1.1. Вызывает обработчик для указанного события. Метод появился в JavaScript 1.2. Возвращает форму, которой принадлежит кнопка Submit. Возвращает имя кнопки Submit, определенное в атрибуте name. Возвращает тип данной кнопки Submit, определенный в атрибуте type. Возвращает значение данной кнопки Submit, определенное в атрибуте value. Таблица 9.25. Методы И свойства объекта Select. Тип Метод Свойство Элемент Ыиг() focus() ,handleEvent() form length name options selectedlndex type Описание Убирает фокус из списка. Устанавливает фокус на список. Вызывает обработчик для указанного события. Метод появился в JavaScript 1.2. Возвращает форму, которой принадлежит список. Возвращает количество вариантов в списке. Возвращает имя данного списка, указанное в атрибуте name. Возвращает массив, содержащий все элементы списка. Эти элементы создаются при помощи HTML-дескриптора <option>. Это свойство обладает также и подсвойствами — length и selectedlndex. Возвращает целое число, определяющее индекс выбранного в списке варианта. Возвращает тип данного списка, заданный в атрибуте type. Для экземпляров <select>, которые содержат атрибут multiple, это свойство возвращает select- multiple. Экземпляры без этого атрибута возвращают значение select-one. Свойство появилось в JavaScript 1.1. Объект Text Основным элементом для любого приложения, предус- предусматривающего ввод данных, по праву считается поле, в. котором пользователь может набирать информацию. Объект Text служит в качестве своего рода устройства захвата данных. В табл. 9.26 перечислены свойства и методы объекта Text. Объект Textarea Рассмотрим связанный с объектом Text объект Textarea, который вместо одной позволяет вводить множество Таблица 9.26. Методы и свойства объекта Text. строк. Тем, кто имел дело с другими средами програм- программирования, гораздо проще считать объект Textarea memo-полем (т.е. полем для заметок). В табл. 9.27 пере- перечислены свойства и методы объекта Textarea. Объекты четвертого уровня В JavaScript 1.4 был введен единственный объект четвер- четвертого уровня — подобъект объекта Select. Поскольку информация о нем пока не устоялась, стоит подождать завершения разработки ECMAScript и Document Object Module (DOM). Тип Элемент Описание Убирает фокус из текстового поля. Устанавливает фокус на текстовое поле. Вызывает обработчик для указанного события; метод появился в JavaScript 1.2. Выделяет текст в текстовом поле. Возвращает значение текстового поля, определенное атрибутом value. Обратите внимание, что это свойство не поддерживается браузерами Opera. Метод СВОЙСТВО' 5 '"'58 biur() focus() handleEvent() select() defaultValue
Базовое подмножество языка JavaScript Тип Часть II Элемент Описание form name type value Возвращает форму, которой принадлежит текстовое поле. Возвращает имя текстового поля, определенное атрибутом name. Возвращает тип текстового поля, заданный в атрибуте type (всегда text). Свойство появилось в JavaScript 1.1. Возвращает значение, которое фактически отображается в текстовом поле. Таблица 9.27. Методы и свойства объекта Textarea. Тип Элемент Описание Метод Свойство Ыиг() focusQ handleEvent() selectQ defaultValue form name type value Убирает фокус из текстовой области. Устанавливает фокус на текстовую область. Вызывает обработчик для указанного события. Метод появился в JavaScript 1.2. Выделяет текст в текстовой области. Возвращает для текстовой области значение, находящееся между парой дескрипторов <textarea>. Это свойство не поддерживается браузерами Opera. Возвращает форму, которой принадлежит текстовая область. Возвращает имя данной текстовой области, определенное в атрибуте name. Возвращает тип данной текстовой области, указанный в атрибуте type (всегда textarea). Свойство появилось в JavaScript 1.1. Возвращает значение, которое фактически отображается в текстовой области. Объект Option Объект Option обычно используется для ссылки на раз- различные элементы <option>, которые находятся между открывающим и закрывающим дескрипторами <select>. Таблица 9.28 содержит свойства объекта Option. Резюме Объекты языка JavaScript со стороны клиента служат в качестве фундаментальных инструментальных средств для создания сценариев. В главе было дано представле- Таблица 9.28. Свойства объекта Option. ние об иерархии JavaScript-объектов и о каждом из при- принадлежащих ей объектов. Существенная часть объектной модели — ни что иное как элементы HTML, которые "превращены" в объекты для организации работы с HTML-дескрипторами на объектно-ориентированный манер. Если вы пришли из мира HTML, начинайте воспринимать эти элементы не как дескрипторы, но как объекты. В главе 10 рассмат- рассматриваются базовые языковые объекты, в главе 11 обсуж- обсуждаются проблемы создания собственных объектов и, наконец, в главе 12 дается представление о серверной ча- части JavaScript и объектах, присутствующих в этой среде. Свойства Описание defaultSelected Ссылается на опцию, которая выбрана по умолчанию в блоке выбора. Свойство появилось в JavaScript 1.1. index Ссылается на отсчитываемый от нуля индекс элемента в массиве Select.options. selected Ссылается на выбранное значение списка выбора. Свойство появилось в JavaScript 1.2. text Ссылается на текст опции, value Ссылается на значение, возвращаемое в случае выбора опции.
Основные объекты языка В ЭТОЙ ГЛАВЕ Объект Global Объект String Объект RegExp Объект Array Объект Date Объект Math Объект Boolean Объект Number Объект Function Любой читатель вправе заявить, что клиентские объекты • - основа JavaScript. При создании сложных приложений JavaScript разработчик сталкивается с ос- основными объектами языка, отличительные особеннос- особенности которых — непротиворечивость объектов различных поставщиков (Microsoft, Netscape, Sun, Be, Opera Software) и поддержка различных платформ, как сервер- серверных, так и клиентских. Эти объекты подчиняются стан- стандарту ECMAScript 1.0. В данной главе рассматриваются объекты String, RegExp, Array, Date, Math, Boolean, Number, Function, а также особенности их использования в различных вер- версиях JavaScript. '' ПРИМЕЧАНИЕ „ ¦ ". vp^f-i^'1"" '" '' " " " > ' '"'¦¦* Полный синтаксис каждого объекта в книге не приво- приводится, поскольку его можно найти на сайтах http:// developer.netscape.com для платформы Netscape и http://msdn.microsoft.com/scripting для платформы Microsoft. Кроме того, на сайте http://www.mozilla.org/js всегда доступна информация по версии Navigator с открытым кодом (известной также как версия 5.0). Объект01оЬа1 Даже программистов, имеющих опыт работы с JavaScript, должно заинтересовать, что же это за зверь такой, объект Global. Действительно, не каждый слы- слышал о нем. Перед тем как приступить к углубленному изучению свойств и методов объекта, стоит вспомнить некоторые основные понятия. Объект Global впервые появился, когда ECMAScript 1.0 стал восприниматься в качестве стандарта. А потом компания Microsoft достаточно "внезапно" объединила высокоуровневые свойства и методы в объект Global, да и Netscape упомянула о нем в нескольких своих доку- ментациях. Вот так и появился объект Global — высо- высокоуровневые свойства и методы и при этом отсутствие родительского объекта. Объект Global имеет множество свойств и методов, которые перечислены в табл. 10.1. Несложно убедиться, что большинство из них используется в сценариях JavaScript. Объект String Строки — это фундаментальное понятие любого языка программирования. Строка, представляющая собой на- набор алфавитно-цифровых символов, может быть либо текстовой (литеральной) строкой, такой как "Не морочь- морочьте голову", либо строковой переменной, например, thePhrase. В главе 5 строки рассматривались с точки зре- зрения типа данных, однако в JavaScript строки могут быть также и объектами со своим набором методов и свойств. По мере совершенствования JavaScript, строки при- приобретали все большее значение. В начальной версии JavaScript они не являлись реальными объектами, но начиная с JavaScript 1.1 ситуация изменилась. Напри- Например, для создании строки и проверки ее длины в JavaScript 1.1 можно воспользоваться следующим кодом: <script type="text/javascript"> <!-- var str = "Здравствуйте, я — король."; alert(str.length); //--> </script> Начиная с JavaScript 1.1, для создания экземпляра объекта String можно пользоваться оператором new. Применение браузера, не поддерживающего определе- определение объекта String, приведет к ошибке, гласящей, что String не определен.
Базовое подмножество языка JavaScript Часть II Следующий пример показывает, как будет выглядеть приведенный выше код для браузеров, поддерживающих JavaScript 1.1: <script type="text/javascript" language="JavaScriptl.1"> <! -- var str = "Здравствуйте, я — король." ; alert (str.length) ; </script> Какова же цель явного объявления объекта String? Все дело в том, что доступ к объекту String может про- производиться из других фреймов, а это более удобно и эф- эффективно по сравнению с JavaScript 1.0. Например, если требуется получить доступ к переменной CUStName из родительского окна, необходимо записать такой код: ¦var customer = new String () ; customer = parent. custName; В случае JavaScript 1.0 для успешной работы с вы- выражением в его конце следует добавить пустую строку: Таблица 10.1. Методы и свойства объекта Global. var customer = parent. custName + ""; Кроме преимущества своей простоты, данный метод относится к понятию хорошего тона в программирова- программировании. В настоящий момент ECMAScript является стан- стандартом, a JavaScript и JScript — его воплощениями. Программист должен иметь уверенность, что в коде используются корректный синтаксис и семантика, а работа кода — безукоризненна. JavaScript позволяет ма- манипулировать строками. Соответствующие свойства и методы сведены в табл. 10.2. Поскольку строки — весь- весьма частые гости, с особенностями их использования стоит познакомиться поподробней. Строки относятся к одному из важнейших типов данных, поэтому просто необходимо уметь выделять данные из строки получать о них информацию. Напри- Например, для определения размера строки можно восполь- воспользоваться свойством length. В рассмотренном примере возвращается 13: var myString = new String ("Это мой день."); var len = myString.length; Tun Метод Свойство Элемент escape() eval() isFinite() isNaN() parseFloat() parselntQ unescapeO Infinity NaN Описание Возвращает объект String, в котором все алфавитно-цифровые символы преобразовываются в их цифровые эквиваленты. Принимает строку с операторами JavaScript и тестирует ее на предмет корректности синтаксиса. Определяет, имеет ли переменная конечные границы. Метод появился в JavaScript 1.3. Определяет, содержит ли переменная допустимое число. Метод появился в JavaScript 1.1. Выполняет преобразование строкового аргумента в число с плавающей точкой (float). Выполняет преобразование строкового аргумента в целое число. Принимает шестнадцатиричное значение и возвращает ASCII-эквивалент в кодовой таблице ISO-Latin-1. Ключевое слово, используемое для представления плюс бесконечности. Свойство появилось в JavaScript 1.3. Представляет объект, не имеющий эквивалентов ни с одним из чисел. Свойство появилось в JavaScript 1.3. Таблица 10.2. Методы и свойства объекта String. Тип Элемент Описание Метод anchor() Создает экземпляр дескриптора <а> с атрибутом name, принимающим значение строки, передаваемой методу. big() Преобразует строку в экземпляр дескриптора <big>. blink() Преобразует строку в экземпляр дескриптора <blink>. bold() Преобразует строку в экземпляр дескриптора <bold>. charAt() Возвращает символ строки, расположенный по заданному индексу. CharCodeAt() Возвращает код символа ISO-Latin-1, расположенного по индексу, переданному в метод. concat() Связывает две переданные строки в одну новую. Метод появился в JavaScript 1.2. fixed() Преобразует строку в экземпляр дескриптора <tt>, определяющего шрифт фиксированной ширины.
Основные объектны языка Глава 10 Тип Элемент Описание fontcolor() Устанавливает атрибут color экземпляра дескриптора <font>. fontsizeQ Устанавливает атрибут size экземпляра дескриптора <font>. fromCharCode() Возвращает строковое значение числа ISO-Latin-1, переданное методу. indexOf() Возвращает позицию первого вхождения строки, переданной методу, в экземпляре объекта String. italicsQ Преобразует строку в экземпляр дескриптора <i>. lastlndexOfQ Возвращает позицию последнего вхождения строки, переданной методу, в экземпляре объекта String. link() Преобразует строку в экземпляр дескриптора <а> и устанавливает атрибут href в значение URL match() Возвращает массив, основанный на регулярном выражении, переданном в метод. Метод появился в JavaScript 1.2. replace() Выполняет операцию поиска и замены, заданную регулярным выражением, и заменяет на строку, переданную в метод. Метод появился в JavaScript 1.2. search() Возвращает позицию совпадения с заданной строкой в экземпляре объекта String. Если строка не найдена, возвращается значение -1. Метод был добавлен в JavaScript 1.2. slice() Возвращает часть строки между заданными начальной и конечной позициями. При передаче отрицательного числа отсчет будет выполняться с конца строки. Метод появился в JavaScript 1.2. small() Преобразует строку в экземпляр дескриптора <small>. split() Выполняет разделение строк на сегменты. Размеры сегментов определяются границами строки и экземпляров. Метод появился в JavaScript 1,1. strike() Преобразует строку в экземпляр дескриптора <strike>. sub() Преобразует строку в экземпляр дескриптора <sub>. substr() Возвращает часть строки, которая начинается с заданной позиции и содержит заданное количество символов. При передаче отрицательного числа отсчет будет выполняться с конца строки. Метод появился в JavaScript 1.2. substringO Возвращает часть строки между начальной и конечной позициями. sup() Преобразует строку в экземпляр дескриптора <sup>. toLowerCase() Преобразует символы исходной строки в нижний регистр. toSource() Возвращает строковое представление объекта String. Метод появился в JavaScript 1.3. toUpperCase() Преобразует все символы строки в верхний регистр. Свойство Iength() Возвращает длину строки. prototype() Позволяет добавлять новые свойства в экземпляры объекта String. Свойство появилось в JavaScript 1.1. Кроме того, можно выполнять поиск текста внут- внутри строки, прибегнув к помощи методов indexOf(), lastIndexOf(). Вызывайте их, если требуется отыскать определенные символы или подстроки внутри строки и возвратить соответствующую позицию (или индекс). В то время как indexOf() начинает с левой стороны стро- строки и продвигается вправо, lastIndexOf() выполняет ана- аналогичные действия, но в обратном направлении. Оба метода начинают действовать с позиции 0 и возвраща- возвращают значение -1, если текст не найден. Код в приведен- приведенном ниже примере устанавливает значение переменной results равным 8: var myString = new String ("Каждый день *-> приближает нас к ... светлому будущему."); var results = myString.indexOf("e"); А вот следующий код установит значение перемен- переменной results равным 47: var myString = new String ("Каждый день ^приближает нас к ... светлому будущему."); var results = myString.lastlndexOf("e"); Оба метода имеют второй необязательный параметр, позволяющий определить, с какого места строки начи- начинать поиск. Например, в сценарии из листинга 10.1 ре- реализован поиск в переменной graf и подсчет количества вхождений буквы е.
Лазовое подмножество языка JavaScript Часть II Листинг 10.1. Применение метода indexOf() для поиска всех букв е, встречаемых в предложении. <SCript type=" text/ javascript" language="JavaScriptl.1"> <! — // Объявление переменных var pos = 0; var num = -1; var i = -1; var graf = "Деньш не приносят счастья," + "однако обеспечивают спокойствие и Суверенность." ; // Поиск в строке с подсчетом количества // встречаемых "е" while (pos != -1) { pos = graf.indexOf("e", i + 1) ; num += 1 ; i = pos; : // Поместить ответ на страницу document.write(graf) document.write("<hr size='l'>") document.write("В параграфе найдено " букв s.") ; document.close() </script> + num + На рис. 10.1 показан результат выполнения сцена- сценария. •1 (Thwart Деньги не приносят СЧЭСТЬЯ.ОДНЗКО обеспечивают спокойствие и уверенность В параграфе найдено 7 букв 6 РИСУНОК 10.1 Пример использования метода indexOf(). Если требуется достичь большего, нежели поиск позиции определенного символа, с помощью метода substring() можно получить часть строковой переменной или литерала. substring() принимает два параметра - начальную и конечную позиции подстроки. Точно так же как и indexOf() и lastIndexOf(), данный метод начи- начинает отсчет с нуля, т.е. первая позиция в строке рассмат- рассматривается как 0-вая. В следующем коде переменная results получит значение Новая: var myString = new String ("Новая Англи: var results = myString.substring@,3); Для получения одиночного символа используйте charAt(). Метод CharAt() возвращает символ по указан- указанной позиции, переданной в качестве параметра. В при- приведенном ниже примере results получит значение и: var myString = new String("Слоны и е var results = myString.charAtF); В случае указания позиции, выходящей за пределы строки, возвращается значение -1: var myString = new String ("Агент С var results = myString.charAtB0102); Сущность программ управления строками раскрыва- раскрывается при их объединении с целью решения определен- определенных задач. Давайте рассмотрим обычную программу в JavaScript, которая обеспечивает замену текста внутри строки на какой-либо иной текст. Сначала потребуется создать обобщенную функцию замены строки, исполь- использующую свойство length, а также методы indexOf() и substring(). При решении данной проблемы будут про- продемонстрированы и процедурный, и объектно-ориен- объектно-ориентированный подходы. ПРИМЕЧАНИЕ Поскольку мы намереваемся создать функцию, выпол- выполняющую поиск и замену в строке, нелишним будет упо- упомянуть, что JavaScript ! .2 поддерживает новый объект RegExp, позволяющий выполнять регулярные выраже- выражения над строками. С помощью этого объекта легко вы- выполнять поиск и замену, поскольку он оперирует ме- методами именно этого характера. Данный объект еще будет упоминаться в данной главе, однако подробное его исследование можно отыскать только в главе 31. Примеры манипуляций со строками Придерживаясь традиционного подхода, можно разра- разработать функцию stringReplace, имеющую три параметра: • originalString — исходная строка, в которой будут выполняться замены. ¦• flndText — строка, которую требуется заменить. • replaceText — строка, которая будет вставляться в originalString. Функция использует эту информация для выполне- выполнения замены. Как показано в листинге 10.2, для поиска параметра flndText используется метод indexOf(), а ме- метод substring() удаляет строки, стоящие до и после па- параметра flndText. Функция объединяет preString, replaceText, postString и присваивает результат перемен- переменной originalString.
Основные объекты языка Глава 10 Листинг 10.2. Создание функции, выполняющей поиск и замену в строках. <html> <head> <title>JavaScript Unleashed</ title> <script language="JavaScriptl .1" type="text/javascript"> function stringReplace(originalString, findText, replaceText) { var pos = 0; var len = findText. length; pos = originalString.indexOf (findText); while (pos != -1) { preString = originalString. substring @, pos) ; poststring = originalString. substring (pos + len, originalString. length) ; originalString = preString + replaceText + poststring; pos = originalString. indexOf(findText) ; J return originalString; </script>' </head> <body> <script language="JavaScriptl .1" type="text/javascript"> / / Объявление переменных var origString = new String ( "Allen") ; var findString = new String ("All") ; var replaoeString = new String ( "Ell" ) ; var resultstring = stringReplace (origString, findString, replacestring) // Отображение результатов на странице document.write ("The original string was: " + origString + "<br>"); document, write ("We searched for: " + findString + "<br>") ; document, write ("We replaced it with: " + replacestring + "<hr size=' 1 ¦>"),¦ document.write ("The result was: " + resultstring); II—> </script> </body> </html> Данная операция продолжается до тех пор, пока findText встречается в строке. Если findText более не найдена, пользователю возвращается новое значение originalString. При разработке этой же функции можно воспользо- воспользоваться возможностями объекта-прототипа JavaScript 1.1 и добавить метод replace() в объектный тип String. Для работы внутри объектной оболочки потребуется изме- изменить структуру кода stringReplace(). Результат описан- описанных действий показан в листинге 10.3. Вовлечь в действие метод гер1асе() можно за счет создания объекта String, установки его значения, а за- затем вызова созданного метода для замены всех вхожде- вхождений определенной строки. Форматирование строк В JavaScript существует несколько способов форматиро- форматирования строк. Многие из них являются эквивалентами дескрипторов форматирования HTML. Это не только гораздо проще постоянного объединения HTML-деск- HTML-дескрипторов в строки, но также и способ применения объектно-ориентированного подхода к разработке. Другими словами, если есть строковый литерал "Ну и денек выдался сегодня!", который необходимо отфор- отформатировать, можно пойти по одному из путей. Можно добавить дескрипторы форматирования HTML: "<Ь>" + "Ну и денек выдался сегодня! " + "</Ь>" Или воспользоваться методом bold() объекта String: var myString = new String ("Ну и денек выдался '••сегодня! ") ; var results = myString.bold() ; В конечном итоге, возвращается следующий HTML- текст: <Ь>Ну и денек выдался сегодня!</Ь> ^ПРИМЕЧАНИЕ Щ Учитывайте контекст, в котором используются мето- методы форматирования. Их нельзя применять за предела- пределами сценария JavaScript в качестве замены дескрипто- дескрипторов форматирования HTML.
Базовое подмножество языка JavaScript Часть I! Листинг 10.3. Добавление метода replaceQ в объект String. <html> <head> <title>JavaScript Unleashed</title> ¦<script language="JavaScriptl .1" type="text/javascript"> . // Определение нового метода для объекта String String.prototype.replace = stringReplace; function stringReplace (findText, replaceText) { // Эту переменную необходимо добавить для унаследования вызываемого объекта var originalstring = new String (this); var pos = 0; var len = f indText. length ; pos = originalString.indexOf (findText) ; while (pos != -1) { preString = originalstring. substring @, pos) ¦ postString = originalstring. substring (pos + len, originalstring. length) ; originalstring = preString + replaceText + postString; pos = originalString.indexOf (findText) ; \ return originalstring; 1 II—> </script> </head> <body> <script language="JavaScriptl.1" type="text/javascript"> <! — // Объявление переменных var origString = new String ("Allen" ); var findString = new String ("All") ; var replaceString = new String("Ell") ; // Заметили отличия? var resultstring = origString. replace (findString, replaceString) У/ Отображение результатов на странице document.write ("The original string was: " + origString + "<br>") ; document.write("We searched for: " + findString + "<br>"); document.write("We replaced it with: " + replaceString + "<hr size='l'>"); document.write("The result was: " + resultstring); II—> </script> </body> </html> Для более подробного знакомства с базовыми мето- методами форматирования JavaScript создадим пример стра- страницы на JavaScript. Она обеспечит форматирование определенной пользователем строки в соответствие с доступными возможностями HTML. Реализация пре- предусматривает использование HTML-формы. Код предполагает создание метода showWindow(), вызываемого в результате щелчка на кнопке Show. Ме- Метод присваивает значение текстового поля формы стро- строковой переменной txt. Каждая из опций форматирования, представленная флажком, принимает значение либо true, либо false. Кроме того, имеется код, выясняющий, установлен ли конкретный флажок. В конечном итоге, к переменной txt применяется соответствующий метод форматирова- форматирования. Опции форматирования не являются взаимоисклю- взаимоисключающими, хотя установка некоторых из них может при- привести к отмене других. В результате появляется возмож- возможность одновременного использования любого числа методов. JavaScript остается только обработать каждый из методов, последовательно добавляя тот или иной HTML-дескриптор. Определение цвета и размера шрифта не сводится к простой логической операции. Напротив, выполняется запрос требуемых параметров. Для упрощения выбора
Основные объекты языка значений параметров форма содержит элементы управ- управления типа списков. В завершение всего, переменная txt при помощи метода document.write() выводится в новое окно, кото- которое тут же и создается. Полная строка записывается в новое окно вместе со всеми дескрипторами форматиро- форматирования, окружающими текст. На рис. 10.2 показано окно со всеми опциями, а на рис. 10.3 — результирующее окно для выбранных па- параметров. В листинге 10.4 приводится полный исходный код рассмотренного примера. String Object Formatting String 1»-"° •""'" Slyln: P Big П Efak. Г ВоИ Г feed & lakes Г Small Pi Stake Г Sub Г Sup F»nc Color \ black ;*) Snc:'[5 jij РИСУНОК 10.2. Страница выбора опций форматирования. РИСУНОК 10.3. Результат форматирования строки. НАПОМИНАНИЕ Методы tollpperCasel) и toLowerCasel) работают в со- соответствие с назначенным планом. Они используются при сравнении текста без учета регистра. Например, при сравнении введенного пользователем текста со ¦строковым литералом лучше перевести обе строки либо к верхнему, либо к нижнему регистру. Для создания объектов Link и Anchor можно вос- воспользоваться методами link() и anchor() объекта String. Данные методы существенно упрощают работу с точка- точками привязки и ссылками в коде, минимизируя длинню- длиннющие строки HTML-дескрипторов. Для иллюстрации сказанного воспользуемся примером, аналогичным пре- предыдущему примеру форматирования. Метод, подобный showWindow()CanycKaeMbiil обра- обработчиком событий onClick кнопки Show), обрабатыва- обрабатывает выбранные пользователем опции, и обращается либо к методу link(), либо к методу anchorQ переменной txt. Листинг 10.4. Исходный код сценария форматирования строки. <html> <head> <title>String Object Formatting</title> <script language="JavaScriptl .1" type="text/javascript"> function showWindow( ) { // Объявление переменных var txt = document, f orml. stringField. value; var clr = " var sze = ""; // Проверка выбранных опций if ( document. f orml. bigBox . checked) txt = txt.bigO; if (document.forml .blinkBox.checked) txt = txt. blink (); if (document, forml. boldBox . checked) txt = txt. bold {); if (document, f orml . f ixedBox . checked) txt = txt . fixed () ; if (document, f orml .italicsBox. checked) txt = txt. italics () ; if (document, forml. smallBox. checked) txt = txt. small (); if (document, f orml. strikeBox. checked) txt = txt. strike () ; if (document, forml. subBox. checked) txt = txt.sub(); if (document, f orml. supBox. checked) txt = txt. sup () ; .// Специальная проверка элементов управления типа списков clr = document. forml. colorList. options [document .f orml. colorList. options, selectedlndex] .text; txt = txt. fontcolor (clr) ; sze = document.forml.sizeList.options[document, forml.sizeList.options.selectedlndex] .text; txt = txt.fontsize(sze) ;
Базовое подмножество языка JavaScript fil Часть II // Открытие нового окна для отображения результатов objWindow = window.open("", "" , "width=600,height=300") ; objWindow.document.write(txt); objWindow.document.close(); i </script> </head> <body> <h:L> String Object Formatting <hr> <form method="POST" name="forml"> <p> <strong> String: </strong> <input type=text size=40 maxlength=256 name="stringField"> <strong> Style-. </strong> <input type=checkbox name="bigBox" value="ON"> Big <input type=checkbox name="blinkBox" value="ON"> Blink <input type=checkbox name="boldBox" value="ON"> Bold <input type=checkbox name="fixedBox" value="ON"> Fixed <input type=checkbox name="italicsBox" value="ON"> Italics <input type=checkbox name="smallBox" value="ON"> Small <input type=checkbox name="strikeBox" value="ON"> Strike <input type=checkbox name="subBox" value="ON"> Sub <input type=checkbox name="supBox" value="ON"> Sup <strong> Font: </strong> Color: <select name="colorList" size=l> <option selected>black</option> <option>green</option> <option>red</option>- </select> Size: <select name="sizeList" size=l> <option selected>K/option> <option>2</option> <option>3</option> <option>4</option> <option>5</option> <option>6</option> <opt ion>7</opt ion> </select> <input type="button" name="Show" value="Show" onClick="showWindow() </form> </body> </html>
Основные объекты языки На рис. 10.4 показана форма HTML, позволяющая определять элементы гипертекстовой ссылки: текст, наименованиепривязки/ссылкии1ШЬ/привязка, соот- соответствующая подчеркнутому тексту. String Object Hypertext Formatting I « link Г Anchor Jump To: ^hrtpjy/www • nw-e РИСУНОК 10.4. Применение гипертекстового форматирования к объекту String. На рис. 10.5 изображено результирующее окно с уже созданной гипертекстовой ссылкой. 1РИСУНОК 10.5. Создание объекта Link с использованием метода link(). В листинге 10.5 находится полный исходный код рассмотренного примера. Работа со специальными символами В любом языке программирования, рано или поздно, придется столкнуться с определенными символами, создающими определенные сложности при использова- использовании их в строках. Для представления специальных сим- символов в JavaScript применяется обратная косая черта (\), за которой следует собственно символ либо его код. В табл. 10.3 перечислены специальные символы JavaScript. Листинг 10.5. Исходный код примера страницы, форматирующей объект String при помощи дескриптора <а>. <html> <head> <title>String Object Hypertext Formatting</title> <script language="JavaScriptl.1" type="text/javascript"> <! — function showWindow () ( var txt = document.forml.stringField.value if (document.forml.hypertext[0].checked){ txt = txt.link(document.forml.jumptoField.value); }else{ if (document, f orml .hypertext [1] . checked) { txt = txt.anchor (document, forml. jumptoField. value) ; // Создание нового окна для помещения в него результатов objWindow = window.open("", '","width=600,height=300") ; objWindow.document.write(txt); objWindow.document.close(); 1 II— > </script> </head> <body> String Object Hypertext Formatting <hr> <form method="POST" name-"forml"> Text:
Базовое подмножество языка JavaScript Часть II <input type=text size=20 maxlength=256 name="stringField"> <input type=radio name="hypertext" value="Link" checked> Link: <input type=radio name="hypertext" value="Anchor"> Anchor: Jump To: <input type=text size=20 maxlength=256 name="jumptoField"> </p> <input type="button" name="Show" value="Show" onClick="showWindow(>"> </form> </body> </html> Таблица 10.3 Специальные символы JavaScript Символ Описание ¦ \n V \f \ь V V Табуляция Новая строка Возврат каретки Перевод страницы Обратная косая черта Забой Двойные кавычки Одинарные кавычки Например, если в строковом литерале необходимо использовать обратную косую черту, поступите следу- следующим образом: var myString = new String ("Ищите свой файл в ¦¦•каталоге C:\\WINDOWS\\TEMP") ; Подставив строку myString в метод document.write(), на экране отобразится: Ищите свой файл в каталоге С НАПОМИНАНИЕ В окне сообщений, отображаемом в результате вызова alertl), символ \г обеспечивает возврат каретки. Для исключительного удобства использования внут- внутренних символов их можно присвоить переменным с осмысленными именами. Если же частота их примене- применения очень высока, можно извлечь определенные "кон- "константы" из кодовой библиотеки JavaScript и использо- использовать их снова и снова. В листинге 10.6 внутренние символы рассматриваются как константы и присутству- присутствуют в обращениях к методу document.write(). Листинг 10.6. Использование специальных символов. <script type="text/javascript"> <!— // Константы для представления внутренних // символов var TAB = "\t"; var CR = "\r" ,- var LF = "\n"; var CRLF = "\r\n" ; var FF = "\f"; var dquote = ¦ V ; var SQUOTE = "\' "; var BACKSLASH = "\\"; var BACKSPACE = "\b"; document. write("CTan6eul" + TAB + "Ст< " + TAB + "СтолбецЗ") II—> </script> Помимо внутренних символов JavaScript позволяет работать с другими значениями, которые нельзя отне- отнести к алфавитно-цифровым. Если требуется преобразо- преобразовать подобное значение в ASCII-значение, стоит при- прибегнуть к методу escape(), например: escape("Нельзя не любить wсимвол тильды <~)"); столь уважаемый Возвращаемое значение выглядит так: Нельзя%20не%2 0любить%20столь%20уважаемый%2 0 "-•символ%20тильды%28%7Е%29 Если требуется преобразовать ASCII- строку, воз- возможно, строку, переданную сервером, воспользуйтесь методом unescape(): unescape("Пишите%20мне%20по%20адресу%20зотеопе "¦¦ @ anywhere .сот% 21"); Данный код возвращает строковое значение: Пишите мне по адресу someone@anywhe: Преобразование строк и чисел JavaScript обеспечивает два встроенных метода для пре- преобразования строк в числа: parseint() и parseFloat(). Обе функции в качестве параметров принимают строки и пытаются преобразовывать строковые данные в число- числовые значения. parseintO преобразует строку в целочис- целочисленное значение, a parseRoat() — в значение с плавающей точкой. Например, приведенный ниже код возвращает значение 123:
Основные объекты языка var myString = new String (23.88888"); document.write(parselnt(myString)); Следующий код возвращает значение 1234.0012121: var myString = new String(234.0012121") ; document.write(parseFloat(myString)); Обе программы начинают преобразование с левой стороны строки и продолжают его до тех пор, пока не встретится нечто, не являющееся цифрой @—9), деся- десятичной точкой (.) либо знаком плюса или минуса (+/-). После столкновения с нецифровым символом оставша- оставшаяся часть строки игнорируется. Приведенный ниже код вернет значение 1234.01: var myString = new String (234.01 — это общая '-•сумма") ; document.write(parseFloat(myString)); С другой стороны, следующий код возвращает зна- значение NaN (Not a Number — не число), поскольку знак доллара не является цифрой; var myString = new String < "$1234.01 - это общая w сумма") ; document.write(parseFloat(myString)); При работе с текстовыми объектами без функций преобразования не обойтись. Поскольку свойство value объекта Text возвращает строку, эти данные придется преобразовывать каждый раз, когда дело доходит до необходимости трактовки текста, вводимого пользова- пользователем, как цифрового значения. Можно также преобразовывать численные значения в строки. В версиях, предшествующих JavaScript 1.3, соответствующие встроенные методы отсутствовали. Однако упомянутое действие можно было выполнить, основываясь на том, как JavaScript выполняет операцию сложения (+). Если во время сложения элементов вы- выражения JavaScript встречала строку, с этого момента все выражение расценивалось как строка. Например, .35+100 возвращает цифровое значение 135. С другой стороны, 35+00" в результате дает строковое значе- значение 5100". ПРИМЕЧАНИЕ ." , , . - . ' При работе с объектом Number в среде, поддержи- поддерживающей JavaScript 1.3+, для преобразования в стро- строковые значения можно использовать метод toStringI). Обратите внимание, что JavaScript выполняет опе- операции сложения слева направо, поэтому перед преоб- преобразованием выражения в строку можно сложить, ска- скажем, два числа. Например, 10 + 20 + 0" вернет строковое значение 040", поскольку пара 10 + 20 вы- вычисляется до прибавления результата к строковому зна- значению. А вот 0" +10 + 20 выдает в качестве резуль- результата строковое значение 01020" из-за того, что левее всех числовых значений находится строковый литерал. Глава 10 Многие языки программирования требуют обяза- обязательного преобразования числовых значений перед их использованием в качестве строковых. Все что требует- требуется предпринять — это либо поместить числовое значе- значение в строковое выражение, либо добавить к нему пус- пустую строку. Например, выражение 1300+ "" возвращает строковое значение 300". Вместо того чтобы каждый раз для преобразования добавлять пустую строку, мож- можно записать простую функцию: function numToString(number) ( number += " " ; return number; '_] В листинге 10.7 находится сценарий, в котором ис- используется приведенная выше функция. Первое окно предупреждений выведет на экран в качестве типа Number. После выполнения функции numToString() во втором окне будет отображаться String. Листинг 10.7. Преобразование Number в String. <script type="text/javascript"> <!-- function numToString (number) { number += "" ; return number; J var number = 100; alert(typeof number); number = numToString (number) ; alert(typeof number); //--> </script> Объект RegExp В предыдущем разделе упоминалось о возможности со- создания функций, выполняющих вычисления и поиско- поисковые операции. В JavaScript 1.2 появился базовый объект RegExp, позволяющий выполнять регулярные выраже- выражения над строками. Поскольку глава 31 обеспечивает достаточно деталь- нос рассмотрение данной темы, не имеет смысла углуб- углубляться в нее сейчас. В табл. 10.4 сведены свойства и методы объекта RegExp. Объект Array Массивы являются основой практически любого совре- современного языка программирования, и JavaScript — тому не исключение. Здесь имеется возможность создавать массивы и работать с ними. Массив (array) — это кон- контейнер, содержащий элементы данных. Каждый из эле- элементов массива — отдельное значение, но все они су- существуют как часть массива. Доступ к ним возможен только через сам массив. В табл. 10.5 сведены все мето- методы и свойства объекта Array.
Базовое подмножество языка JavaScript Часть И Таблица 10.4. Методы и свойства объекта RegExp. Тип Элемент Описание Метод Свойство compileO ехес() test() iRegExp.$* RegExp.$& RegExp.&_ RegExp.&' RegExp.$' 'RegExp.$+ RegExp.$1,$2,"$9 global ignoreCase input lastindex lastMatch lastParen leftContext multiline right Context source Компилирует регулярное выражение для ускорения его выполнения. Выполняет поиск совпадений в строковом параметре. Проверяет наличие совпадений в строковом параметре. Представляет multiline. Представляет last match. Представляет input. Представляет leftContext. Представляет rightContext. Представляет lastParen. Представляет совпавшие подстроки. Проверяет, какие возможные совпадения были найдены Проверяет, игнорировался ли регистр во время поиска. Строка, в которой осуществляется поиске помощью регулярного выражения. Определяет индекс, с которого начинается поиск следующей строки. Последние совпавшие символы. Последняя совпавшая подстрока, взятая в круглые скобки. Подстрока, предшествующая последнему совпадению. Проверяет, должен ли выполняться поиск во множестве строк. Подстрока, следующая за последним совпадением. Шаблон строки. Таблица 10.5 Методы и свойства объекта Array. Тип Элемент Описание Метод Свойство concat() рор() push() reverse() shift() slice() sort() splice(> toSource() toStringO unshift() valueOf() index input lengthi prototype Соединяет элементы существующего массива. Метод появился в JavaScript 1.2. Соединяет все элементы массива в одну строку. Удаляет последний элемент массива. Добавляет элементы в конец массива. Изменяет порядок следования элементов в массиве. Метод появился в JavaScript 1.2. Удаляет элементы в начале массива. Метод появился в JavaScript 1.2. Возвращает часть массива. Метод появился в JavaScript 1.2 Сортирует элементы в массиве. Вставляет и удаляет элементы из массива. Метод появился в JavaScript 1.2. Преобразует элементы в строку с квадратными скобками. Метод появился в JavaScript 1.3. Преобразует элементы массива в строку. Добавляет элементы в начало массива. Метод появился в JavaScript 1.2. Возвращает массив элементов, отделенных запятыми. Возвращает индекс совпадения в строке для массива, созданного в соответствие с регулярным выражением. Появилось в JavaScript 1.2. Для массива, созданного в соответствие с регулярным выражением свойство возвращает исходную строку. Появилось в JavaScript 1.2. Количество элементов в массиве. .Позволяет добавлять свойства к экземплярам объекта Array. Свойство появилось в JavaScript 1.1.
Основные объекты языка Несмотря на то что в строго типизированных языках все значения элементов массива должны иметь оди- одинаковый тип, в JavaScript это необязательно. Массив может содержать данные различных типов, точно так же как объект имеет свойства разных видов. ¦ПРЕДУПРЕЖДЕНИЕ ^ Ц11Ш" , '^ ' - ' ^ В JavaScript массив не является родным объектом — объект Array появился только в JavaScript 1.1. Для оп- определения массива в JavaScript требовалось создавать функцию. Заметьте, что он не будет обладать всей функциональностью родного объекта Array. function createArray(size) { this, length = size; for (var i = 1; i <= size; i-l—Ь) { this[i] = null ; return this; I Для определения или доступа к какому-либо эле- элементу к переменной массива необходимо приписать скобки и задать индексное значение. Например, для оп- определения массива coffee необходимо сделать следую- следующее: coffee[0] coffee[1] coffee[2] coffee[3] coffee [4] coffee[5] coffee[6] "Ethiopian Sidamo" "Kenyan" "Cafe Verona" "Sumatra" "Costa Rica" '"Columbian" "Bristan" Если нужно использовать один из элементов масси- массива внутри сценария, доступ к ним можно получить с помошью переменной массива и значения, которое представляет положение элемента внутри массива. Ото- Отображение на экране строки Мой любимый сорт кофе — Ethiopian Sidamo осуществляет такая срока кода; Document .write ("Мой любимый сорт кофе — " + coffee [0] ) ; Если читатель незнаком с массивами, то ближайший эквивалент в JavaScript — это нумерованный список. Пусть список состоит из 10 пунктов. 1. JavaScript 7. Java 3. Delphi 4. C++ 5. Visual Basic 6. Oracle Power Objects 7. SmallTalk Глава 10 8. PowerBuilder 9. Paradox 10. Access Компоновка этой группы в массив JavaScript пока- показана ниже. Особенность заключается в том, что масси- массивы имеют нулевую базу, т.е. индекс первого элемента равен 0: devTools[0] devTools[1] devTools[2] devTools[3] devTools[4] devTools[5] devTools[6] devTools[7] devTools[8] devTools[9] "JavaScript" "Java" "Delphi" "C++" "Visual Basic" "Oracle Power Objects'' "SmallTalk" "PowerBuilder" "Paradox" "Access" Экземпляр объекта Array создается при помощи опе- оператора new и операторов, заполняющих массив элемен- элементами данных. Например, для упоминаемого ранее мас- массива coffee код должен выглядеть следующим образом: ¦¦ new Array () ; "Ethiopian Sidamo" "Kenyan"; "Cafe Verona" ; "Sumatra"; "Costa Rica"; "Columbian"; "Bristan"; var coffee == coffee[0] = = coffee[1] == coffee[21 = = coffee[3] = = coffee[4] = = coffee [5] =» coffee[6] = = MjoBETi- '¦' •¦-¦¦:-", Альтернативой определению объекта Array может быть указание элементов данных как параметров зап- запроса new. Следующая строка является функциональ- функциональным эквивалентом предыдущего примера. var coffee = new Array ("Ethiopian Sidamo", "Kenyan", "Cafe Verona", "Sumatra", "Costa Rica", "Columbian", "Bristan"); Обратите внимание, что размер массива явно не за- задается; это не характерно для многих языков програм- программирования. В JavaScript определение размера массива не обязательно. Именно это свойство позволяет расширить массив, добавляя новые элементы данных. С другой стороны, если необходимо, размер массива можно за- задать явно в new: var coffee = new Array G>; Изменение размеров массива также можно осуще- осуществить путем определения элемента данных в позиции п. Если п превышает существующее количество элемен- элементов в массиве, размер массива увеличивается до п+1. Посмотрите на следующий пример: var javaDrinks = new Array () ; javaDrinks[0] = "Regular coffee"; javaDrinks[1] = "Decaf coffee";
Базовое подмножество языка JavaScript Часть II javaDrinks[2] = "Cafe Mocha"; javaDrinks [ 3] = "Cafe au Lait"; javaDrinks[199J = "Cafe Latte" ; Размер массива javaDrinks будет составлять 200, даже притом, что определено только 5 элементов дан- данных. При доступе к неопределенным элементам возвра- возвращается значение null. Выяснить размер массива поможет свойство length объекта Array. Например, если необходимо пройти по всем элементам объекта Array, можно воспользоваться сценарием из листинга 10.8. Листинг 10.8. Вывод на экран содержимого массива. <script language="JavaScriptl .1" -"text/j avas cript"> var coffee coffee [0] = coffee [1] = coffee [2] = coffee[3] = coffee [4] = coffee [5] = coffee[6] ' new Array (> ; "Ethiopian Sidamo" "Kenyan"; "Cafii Verona" ; "Sumatra"; "Costa Rica"; "Columbian"; "Bristan"; Coffees of the World:<p>") ; for (var i = 0; i < coffee, length; i++) { ;.write(i + 1 + ". " + coffee[i] + 1 document, write(,</р>* ) ; </script> На рис. 10.6 показан результат. . ?fe E<S vum'tsSmtM .•U:\TEMPV7EK10 Lffi.hM Coffees of the WmM: J. ?thiopian Sidamo 2. Kenyan 3. Cafe Verona 4. Sumatra 5. Costarica. 6. Columbian 7. Bristatl assets,...-:,, ¦¦*¦;.,.:¦;¦:-,: ШшШВШшш z izl ПРЕДУПРЕЖДЕНИЕ Свойство length объекта Array предназначено только для чтения. Отсюда вывод — изменить размеры мас- массива за счет присваивания нового знач< я свойству length нельзя. . Объект Date 1РИСУНОК 10.6. Использование JavaScript для вывода на экран списка сортов кофе. С помощью объекта Date в JavaScript можно работать со значениями даты и времени. Но перед тем как при- приступить к работе с этим объектом, необходимо разоб- разобраться в трех важных вещах: В соответствие с соглашением UNIX, датой появле- появления JavaScript считается 1 января 1970 Соответ- Соответственно, с датами, предшествующими указанной, ра- работать нельзя. При создании объекта Date базой, на которой осно- основывается отсчет времени внутри объекта, является клиентская машина. Таким образом, на ней желатель- желательно наличие работоспособных и точных часов. Учи- Учитывайте это при написании JavaScript-сценариев, чувствительных ко времени. • JavaScript отслеживает значения даты и времени в форме миллисекунд с момента даты основания A/1/ 1970). Важный набор методов, инкапсулированный внут- внутри объекта Date, принимает и устанавливает значения даты и преобразует их в различные формы. В табл. 10.6 показаны все методы и свойства объекта Date. ПРИМЕЧАНИЕ Как и все остальное в JavaScript, относительные зна- значения даты также имеют нулевую базу. Нав« это может вызвать определенные неудобства, поскольку отсчет дней недели осуществляется от 0 до 6, а не от 1 до 7, и месяцев от 0 до ' ' , а не от 1 до 12. Используя в коде значения подобного рода, следует принимать во внимание нулевую базу. Однако, исключением из правил являются дни меся- месяца, отсчитываемые от 1 до 31 и представляющие со- собой абсолютные значения. Создание объекта Date подобно созданию объектов String или Array. В сценарии эти объекты можно созда- создавать в любых количествах. Используя оператор new, оп- определить объект Date можно так: var dateVariable = new Date ([parameter. Различные группы параметров, необходимые для создания этих объектных экземпляров, перечислены в табл. 10.7.
Основные объекты языка Глава 10 Таблица 10.6. Методы и свойства объекта Date. Тип ¦Элемент Описание Метод getDate() getDayO getFullYear() getHours() getMillisecondsO getMinutesQ getMonth() ¦getSeconds() getTime() getTimeZoneOffset() getUTCDate() getUTCDay() getUTCFullYear() getUTCHoursQ getUTCMilliseconds() getUTCMinutes() getUTCMonth() getUTCSeconds() getYear() parse() setDate() setFullYearf) setHours() setMilliseconds() setMinutes() setMonth() setSeconds() setTimeO setUTCdatef) setUTCFullYear() setUTCHours() setUTMillisecondsf) setUTCMinutes() setUTCMonth() Возвращает день месяца (от 1 до 31). Возвращает день недели (от 0 до 6). Возвращает год в четырех символах по местному времени. Метод появился в JavaScript 1.2. Возвращает час суток (от 0 до 23). Возвращает миллисекунды. Метод появился в JavaScript 1.2. Возвращает минуты в пределах часа (от 0 до 59). Возвращает месяцы года (от 0 до 11). Возвращает секунды (от 0 до 59). Возвращает количество миллисекунд, начиная с 1/1/1970 00:00:00. Возвращает смещение часового пояса в минутах по отношению к GMT/UTC. Возвращает день месяца. Метод появился в JavaScript 1.2. Возвращает день недели, преобразованный к универсальному времени. Метод появился в JavaScript 1.2. Возвращает четырехзначное представление года, преобразованное к универсальному времени. Метод появился в JavaScript 1.2, Возвращает часы, преобразованные к универсальному времени. Метод появился в JavaScript 1.2. Возвращает миллисекунды, преобразованные к универсальному времени. Метод появился в JavaScript 1.2. 'Возвращает минуты, преобразованные к универсальному времени. Метод появился в JavaScript 1.2. Возвращает месяц, преобразованный к универсальному времени. Метод появился в JavaScript 1.2. Возвращает секунды, преобразованные к универсальному времени. Метод появился в JavaScript 1.2. Возвращает номер года, начиная с 1900 г. Преобразует строковые данные в миллисекунды. Устанавливает день месяца (от 1 до 31). Устанавливает год как четырехзначное число. Метод появился в JavaScript 1.2. Устанавливает часы дня (от 0 до 23). Устанавливает миллисекунды. Метод появился в JavaScript 1.2. Устанавливает минуты в часе (от 0 до 59). Устанавливает месяц в году (от 0 до 11). Устанавливает секунды в минуте (от 0 до 59). Устанавливает количество миллисекунд, начиная с 1/1/1970 00:00:00. Устанавливает день месяца в соответствии с универсальным временем. Метод появился в JavaScript 1.2. Устанавливает год как четырехзначное число в соответствии с универсальным временем. Метод появился в JavaScript 1.2. Устанавливает час в соответствии с универсальным временем. Метод появился в JavaScript 1.2. Устанавливает миллисекунды в соответствии с универсальным временем. Метод появился в JavaScript 1.2. Устанавливает минуты в соответствии с универсальным временем. Метод появился в JavaScript 1.2. Устанавливает месяц в соответствии с универсальным временем. Метод появился в JavaScript 1.2.
Базовое подмножество языка JavaScript Тип Часть II Элемент Описание setUTCSecondsQ Устанавливает секунды в соответствии с универсальным временем. Метод появился в JavaScript 1.2. sefYearQ Устанавливает количество лет, начиная с 1900 г. toGMTStringO Преобразует дату в строку в соответствии с мировым форматом. toLocalString() Возвращает строку даты в формате локальной системы. toSourceQ Возвращает источник-объект Date. Метод появился в JavaScript 1.3. toString() Возвращает дату и время как строку в соответствии с местным временем. ToUTCStringO Возвращает данные и время как строку в соответствии с мировым временем (UTC). Метод появился в JavaScript 1.2. UTC() Преобразует значения с разделителями-запятыми в миллисекунды даты по UTC, valueOf() Возвращает эквивалент объекта Date в миллисекундах. Метод появился в JavaScript 1.1. Свойство prototype Свойство, позволяющее добавлять методы и свойства к объекту Date. Свойство появилось в JavaScript 1.1. Таблица Параметр 10.7. Параметры, необходимые Описание ДЛЯ создания экземпляра объекта Date. Пример Отсутствие параметров "месяцдд, гггг чч:мм:сс" гг, мм, дд irr, мм, дц, чч, мм, ее Создает объект с текущими датой и временем. Создает объект с указанными датой (дц — день, гггг — год) и временем (чч — часы, мм — минуты, ее — секунды). При этом все пропущенные значения считаются нулевыми. Создает объект с указанными датой из набора целочисленных значений (гг — год, мм — месяц, дц — день) Созцает объект с указанными цатой и временем из набора целочисленныхзначений(гг— гоц, мм — месяц, дц — цень, чч — часы, мм — минуты, ее — секунцы). При этом все пропущенные значения считаются нулевыми. var today = new Date() var someDate = new Date ("September 27, 2000"; var someDate = new Date@0, 1, 0) var someDate = new Date@0, 7, 24, 6, 29, 50) После создания объекта можно использовать все его методы для получения или установки значения даты. Например, для возврата текущей даты следует записать: var today = new Date (> ; result = today.getDate(); Для изменения месяца, определенного в объекте appt типа Date потребуется записать: var appt = new Date B000,10,20) ; result = appt. setMonth G) ; Раньше упоминалось, что значения даты с нулевой базой осложняют процесс получения даты. Эту труд- трудность несложно обойти, расширив методы объекта Date, создав прототипы более приемлемых методов get. Как известно, JavaScript позволяет расширять воз- возможности встроенных объектов, тем самым позволяя создавать прототипы новых методов или свойств. Все объекты должны быть унаследованы от этого нового прототипа. Добавьте в объект Date следующие новые методы: • getActualMonth() будет возвращать действительное значение для месяца. • getCalendarMonth() будет возвращать название меся- месяца. • getActualDay() будет возвращать текущее численное значение дня недели. • getCalendarDay() будет возвращать название дня не- недели. В листинге 10.9 приводятся определения для каждо- каждого из прототипов перечисленных методов. Данный ли- листинг послужит наглядным примером сохранения обще- общеупотребительных функций во внешней библиотеке JavaScript или в исходном файле, который можно заг- загрузить при помощи атрибута src дескриптора <script>. Листинг 10.9. Расширение объекта Date за счет добавления в него новых методов. <script type=" text/ javascript" language="JavaScriptl.1"> Date . prototype. getActualMonth = getActualMonth; Date.prototype.getActualDay = getActualDay; Date.prototype.getCalendarDay = getCalendarDay; Date.prototype.getCalendarMonth = getCalendarMonth ,¦
Основные объекты языка function getActualMonth() { var n = this. getMonth () ; n += 1; return n ; i function getActualDay() { var n = this.getDay (); n += 1 ; return n, ; } function getCalendarDay() ( var n « this.getDay () ; var dow = new Array G) ; dow[0] = "Sunday"; dow[lj = "Monday"; dow[2] = "Tuesday"; dow[3] = "Wednesday"; dow[4] = "Thursday"; dow[5] = "Friday"; dow[6] = "Saturday"; return dow[n]; j function getCalendarMonth(> { var n = this .getMonth(); var moy = new Array A2) ; moy[0] = "January"; moy[l] = "February"; raoy[2] = "March"; moy[3] = "April"; moy[4] = "May"; moy[5] = "June"; moy[6] = "July"; moy[7] = "August"; moy[8] = "September"; moy[9] = "October"; moy[10] = "November"; moy[11] — "December"; return moy[n]; i // Тестирование вновь созданных методов var today = new Date () ; document.write("<b>I hereby declare that on ' + today.getCalendarDay() + " , the " + today. getDate () + " th day of + today . getCalendarMonth () ¦+ "' in the year " + today.getFullYear () + " A.D. at the " + today.getHours() + "th hour of the day, absolutely nothing wis happening.</b>") ; II—> </script> Псслс объявления методов сценарий создает объект Date и генерирует HTML-документ, используя комби- комбинацию прототипных методов (см. рис. 10.7). Поскольку JavaScript является приложением, работа- работающим в среде World Wide Web, в нем определены мето- методы, работающие с часовыми зонами. getTimezoneOffset() возвращает размер различия в минутах между клиентс- клиентским компьютером и GMT (Greenwich Mean Time - время по Гринвичу). Например, я сейчас нахожусь в во- Глава 10 сточной часовой зоне США. Если мне нужно вернуть часовое смещение временной зоны, я запишу такой код: var today = new Date() ; offset = today.getTimezoneOffset() / 60; if (offset = 5) ( alert("Вы находитесь в восточной временной зоне"); hereby . laje that on Saturday, the 5th day of February in Uu year 2000 AJ>. at the 12Ui hQ»u- of the day, ahsolutetjrnothingishappening- РИСУНОК 10.7. Использованиеусовершенствованных методов get. Рисунок 10.8 показывает результат запуска сценария. Можно выполнять вычисления со значениями дат, определив таким образом количество дней до конца следующего столетия. Даты, используемые в вычисле- вычислениях, необходимо хранить в их собственном миллисе- кундном формате, а затем выделять соответствующие данные. РИСУНОК 10.8. #cna/!b3oeaHHegetTimezoneOffset() для определения временной зоны. Объект Math С целью эффективной организации математических вы- вычислений JavaScript инкапсулирует большое число ма- математических констант и процедур в единый объект Math. Он в некоторой степени отличается от других базовых объектов. Во-первых, можно выполнять базо- базовые арифметические вычисления (сложение, вычитание,, умножение, деление) за пределами объекта Math. До тех пор пока не потребуются сложные математические
Базовое подмножество языка JavaScript Часть II функции, использование данного объекта будет чрезвы- чрезвычайно редким. Во-вторых, хотя и можно создавать экземпляры объектов String, Array, Date при помощи new, все рав- равно работа продолжается с базовым экземпляром Math. Подобное качество позволяет расценивать этот объект как созвучный navigator, который никогда не создается "на лету". Именно поэтому на объект Math ссылаются как на статический (static) объект. Свойства объекта Math — ни что иное как последо- последовательность общих математических констант. Свойства и методы этого объекта сведены в табл. 10.8. Обратите внимание на регистр в именах констант. Несмотря на то что практически все имена свойств JavaScript запи- записываются в нижнем или же в смешанных регистрах, Таблица 10.8. Методы и свойства объекта Math. имена рассматриваемых свойств записаны символами верхнего регистра. Объект Boolean Значения логического типа являются неотъемлемой час- частью любого языка программирования. Объект Boolean, впервые появившийся в JavaScript 1.1, применяется для преобразования значений, не относящихся к логическо- логическому типу, в значения логического типа. В конечном итоге с этим объектом можно работать как с обычным значе- значением логического типа (true или false). Объект Boolean можно создать, прибегнув к уже знакомому оператору new: var booIeanObjectName = new Boolean(initialValue); Tun Элемент Описание Метод abs() Возвращает абсолютное значение. acos() Возвращает значение арккосинуса для аргумента, выраженное в радианах. asin() Возвращает значение арксинуса для аргумента, выраженное в радианах. atan() Возвращает значение арктангенса для аргумента, выраженное в радианах. atan2() Возвращает значение арктангенса для частного от деления аргументов, выраженное в радианах. ceil() Возвращает целое число, большее или равное переданному значению. cos() Косинус для переданного значения. ехр() Возвращает константу Эйлера для степени, переданной в качестве значения. floor() Целое число, меньшее или равное переданному значению. !од() Натуральный логарифм по основанию е. тах() Максимальное число из двух переданных значений. min() Минимальное число из двух переданных значений. pow() Результат возведения первого переданного в качестве аргумента числа в степень второго. Random() Возвращает случайное число между 0 и 1. Метод появился в JavaScript 1.1. roundQ Возвращает значение, округленное до ближайшего целого. sin() Возвращает синус переданного числа, выраженный в радианах. sqrt() Квадратный корень переданного числа. tan() Возвращает тангенс переданного числа, выраженный в радианах. toSource() Копия объекта. Метод был добавлен в JavaScript 1.3. toStringO Строковое представление объекта. Свойство Е Константа Эйлера B.718281828459045). LN2 Натуральный логарифм 2 @.6931471805599453). LN10 Натуральный логарифм 10B.302585092994046). LOG2E Логарифма Е по основанию -2 A.4426950408889633). LOG10E Логарифм Е по основанию -10 @.4342944819032518). PI Число Пи C.141592653589793) SQRT1_2 Квадратный корень 0.5 @.7071067811865476) SQRT2 Квадратный корень 2A.4142135623730951).
Основные объекты языка Параметр initialValue определяет начальные установ- установки объекта.Если параметр принимает значение false, О, null или пустую строку (""), или вообще пропущен, принимается значение по умолчанию, равное false. В противном случае — true. В табл. 10.9 приведены методы и свойства объекта Boolean.. Объект Number Объект Number, поддерживаемый в JavaScript 1.1 и сле- следующих версиях, служит для хранения числовых зна- значений наподобие того, как объект String предназначен для хранения строковых значений. Однако в действи- действительности он используется гораздо реже. Этот объект применяется, если необходимо получить доступ к оп- определенным значениям констант, таким как максималь- максимально или минимально представимыс числа, плюс или минус бесконечность или нечисловые значения (NaN). Упомянутые значения реализованы в виде свойств объекта Number. В табл. 10.10 приведены методы и свой- свойства объекта Number. Как и другие базовые объекты, экземпляры объекта Number в сценарии создаются при помощи оператора new со следующим синтаксисом: var munberObjectName = new Number (initialValue) ; Зачастую объекты Number создаются, когда к ним требуется добавить новые свойства. Например, листинге 10.10 содержит сценарий, демонстрирующий особую полезность объектов Number. Здесь уменьшается необ- Таблица 10.9. Методы и свойства объекта Boolean. Глава 10 ходимость выполнения множества преобразований строк в числа. Результат выполнения сценария показан на рис. 10.9. t* if-* fiu Vftdw HH 1 :',> ~T| $J The speed cKfferencptrtweeu Interstate Highway Speed Lunit ami City Speed Lenit is 30 РИСУНОК 10.9. Использование объекта Number. Объект Function Последний базовый объект, появившийся в JavaScript 1.1. — это Function. Он позволяет определить строку во время выполнения и компилировать ее как функцию. Рассмотрим синтаксис объявления объекта Function. ямяОбъектаРипсЫоп = new Function {[аргумент1, аргуыент2, ... аргументы], (гелоФункции) ; Тип Элемент Описание Метод Возвращает строковое представление простейшего значения Boolean, хранящегося в объекте. Если в объекте содержится true, возвращается строка "true", а если false —то "false". Свойство prototype Это свойство позволяет добавлять методы и свойства в объект Boolean. Таблица 10.10. Методы и свойства объекта Number. Тип Элемент Описание Метод toString() valueOff) Свойство MAX_VALUE MIN_VALUE NaN POSITIVEJNFINITY NEGATIVEJNFINITY prototype Возвращает строковое представление объекта Number. Метод появился в JavaScript 1.3. Возвращает строковое представление заданного объекта Number. Возвращает значение объекта Number как числовой тип данных. Максимальное число A.797693148623157е+308). Минимальное число Eе-324). Специальное нечисловое значение (NaN). Специальное значение бесконечности, возвращаемое в случае переполнения. Специальное значение, представляющее отрицательную бесконечность; возвращается в случае переполнения. Позволяет добавлять новые свойства и методы к объекту Number.
Базовое подмножество языка JavaScript Часть II Листинг 10.10. Создание объекта Number вместо выполнения преобразования строк в числа. <html> <head> <script language="JavaScriptl.1" type="text/javascript"> // Добавление свойства description в объект Number Muniber.prototype, description = null; // Значения ограничений скорости slHighway = new Number F5) ; slCity = new Number C5); slSchoolZone = new Number B5); // Добавление описаний в свойствах description slHighway.description = "Interstate Highway Speed Limit"; slCity.description = "City Speed Limit"; slSchoolZone.description = "School Zone Speed Limit"; .// Вычитание num2 из numl и отображение результата вместе с // описанием исходных значений, function tellDifference(numl, num2) { diff = numl - num2; document.write("The speed difference between " + numl.description + " and " + num2 .description + " is " + diff) ; II—> </script>' </head> <body> <script language="JavaScriptl.1" type="text/javascript"> // Вызов функции tellDifference(slHighway, slCity); II—> </script> </body> </hfanl> Следует учесть, что несмотря на внешнее подобие объекта Function и стандартной функции JavaScript (т.е. function), все же они существенно отличаются друг от друга. Имя объекта Function рассматривается как пере- переменная, представляющая текущее значение функции, определенной в строке new Function, в то время как имя стандартной функции JavaScript переменной не являет- является — это именно имя функции. ПРИМЕЧАНИЕ :, ," .- Л",^ .Г'1* ¦*"*%¦:'¦ Трансляция объекта Function выполняется при каждом его использовании. Неудивительно, что их выполнение происходит гораздо медленнее по сравнению с нор- нормальными функциями JavaScript. Объект Function можно использовать как обработчик событий. Рассмотрим пример; window.onload = new Function("document.bgColor = "aqua1"); Резюме К базовым объектам языка следует относиться как к важнейшим винтикам рабочего механизма JavaScript, поскольку большая часть работы выполняется как раз внутри их конструкций. Кроме того, не забывайте, что именно базовые объекты стандартизируются в соответ- соответствие со спецификацией ECMAScript. Глава была посвящена методике использования ба- базовых объектов языка и описанию особенностей из фун- функционирования в различных версиях браузеров. В сле- следующей главе будут рассматриваться примеры приме- применения массивов и способы создания пользовательских объектов.
Создание пользовательских объектов JavaScript В ЭТОЙ ГЛАВЕ Создание объектов Создание экземпляров объектов Работа с экземплярами объектов Создание составных объектов Динамическое создание объектов Расширение экземпляров объектов Данная глава является логичным продолжением пре- предыдущей. В главе 9 мы много говорили об основах объектно-ориентированного программирования, а в гла- главе 10 — о встроенных объектах языка JavaScript. Но если на этом остановиться, возможности JavaScript мо- могут показаться весьма скудными. Не следует упускать из виду создание собственных пользовательских объектов. Именно этой теме и посвящается данная глава. Создание объектов Пользовательские объекты JavaScript тесно связаны с массивами. Массивы — средство структурирования дан- данных в контейнере. Какими бы мощными не были бы массивы, они не в состоянии удовлетворить все запро- запросы разработчиков. Несмотря на то что массивы хранят данные, они не могут хранить поведение. Как обсуждалось в главе 9, объект содержит и дан- данные, известные как свойства (properties), и поведение, известное как методы (methods). На первый взгляд мо- может показаться, что массив — почти то же самое, что и объект со свойствами, однако есть один нюанс: массив не хранит информацию о способе своей реакции на ме- методы. Наша задача — создать объект, инкапсулирующий элементы данных и обеспечивающий реакцию на вызов методов. Для создания объекта JavaScript необходим конст- конструктор (constructor). Конструктор — это специальная функция JavaScript, которая определяет вид объекта и его поведение. Сам по себе конструктор не создает объекты. Вместо этого он обеспечивает шаблон вида реализованного объекта. (Создание экземпляра объекта называется реализацией (instantiating) объекта.) Базовая структура реализованного объекта выглядит так: function object.{parameterI, parameter2,...\ { this . proper tyl = parameter 1 this. property2 = parameter2 this. property 3 = parameters this . proper ty 4 = parameter! this.methodl = functionl this .method2 = Iuiiclion2 Простота нестоящей структуры конструктора доста- достаточно очевидна. Сначала потребуется присвоить имя самому методу. Имя функции послужит именем объек- объектного типа. Если объект создается с целью представле- представления, скажем, счета-фактуры, назовите его invoice. Иног- Иногда мне встречались программисты, которые в названиях конструкторов использовали глагол; получалось что-то наподобие createlnvoice. Подобная практика может при- привести к снижению удобочитабельности кода, т.к. свой- свойство объекта будет выглядеть как-то так: myDate — createlnvoice.date; Даже еще хуже, если среди методов объекта присут- присутствует create(), код приобретет просто "шикарный" вид: createlnvoice .created ; А вот в случае применения существительных для именования можно надеяться на гораздо более изящный вид: myDate = invoice.date; И invoice.create(); Следующий шаг заключается в добавлении парамет- параметров в функцию для всех свойств объекта. Следуя тако- такому подходу, при реализации объекта значения свойств передаются в функцию в форме параметров. Третьим шагом будет присвоение свойствам объек- объектам значений входных параметров. Ключевое слово this
Базовое подмножество языка JavaScript Часть II очень удобно; оно используется для представления объекта в момент определения свойств. Четвертый шаг связан с определением методов, ко- которыми будет обладать объектный тип. В то время как свойствам присваиваются значения параметров конст- конструктора, методы создаются в виде функций за предела- пределами конструктора и присваиваются определениям мето- метода объекта. Предположим, что необходимо создать пользова- тельскийобъект,применяемыйдляхраненияинформа- ции о любимых книгах. В частности, хотелось, чтобы в нем присутствовало название книги, имя автора (или авторов), ISBN, предмет, которому посвящена книга, и присвоенный ей внутренний рейтинг. Конструктор можно определить следующим образом: function book(title, author, ISBN, subject, rating) I this.title = title; this.author = author; this. ISBN = ISBN; this.subject = subject; this.rating = rating; } Кроме того, хотелось бы добавить метод show(), который будет отображать на экране информацию об объектах. Создадим функцию, размещенную за преде- пределами конструктора: function show () { objwindow = window.open ("", "", "width=600,height=300"); ob jwindow. document. write ("<htmlxbody>" > ; objwindow.document.write("<hl>Object ^Description</hl>"); objwindow.document.write("<p>"); objwindow.document.write("Book Title: " + this.title + "<br>"); objWindow.document.write("Author: " + this.author + "<br>") ,- objwindow.document.write("ISBN: " + this.ISBN + "<br>") ,- objwindow.document.write("Subject: " + this.subject + "<br>"); Листинг 11.1. Определение объекта Book. objwindow.document.write("Allen's Rating: " this.rating + "<br>") ,- objwindow. document.write ("</bodyX/html>") ; objwindow.document.close () ; Несмотря на то что этот код находится за предела- пределами конструктора, можно рассмотреть его как часть опи- описания объекта. Следовательно, в данном случае придется прибегнуть к ключевому слову this. Далее в конструктор добавляется новый вход для метода: function book(title, author, ISBN, subject, rating) { this.title = title; this, author = author; this.ISBN = ISBN; this.subject = subject; this.rating = rating; this. show = show; // Новый метод отображения » Обратите внимание на две детали, относящиеся к описанию метода show(). Во-первых, имя объектного метода совпадает с соответствующей внешней функци- функцией, чего быть не должно. Для большей читабельности одни разработчики используют идентичные имена, а другие — добавляют внешнюю функцию, содержащую в своем имени еще и имя объекта, например, book_ show(). Во-вторых, в конструкторе записывается лишь только имя внешней функции, без круглых скобок. В ранних версиях Netcsape Navigator описание ме- тодатребовалосьрасполагатьдоконструктора, посколь- поскольку все ссылки выполнялись сверху вниз. В Navigator 3+ такого уже нет. Размещение метода show() относитель- относительно метода конструктора в JavaScript роли не играет. Упомянутый факт дает возможность улучшить чи- читабельность кода, разместив описания методов непо- непосредственно под конструктором. Крометого, стоитпо- местить набор функций в комментарий, чтобы они вос- воспринимались как целостная конструкция. В листинге 11.1 приводится полное описание объекта Book, <script type="text/javascript"> <!-- function book(title, author, ISBN, subject, rating) ( this.title = title; this.author = author; this. ISBN = ISBN,- this.subject = subject; this.rating = rating; this. show = show; } function show (У { objwindow = window. open ("", "", "width=600,height=300"); objwindow. document .write {„<htmlXbody >") ; objwindow.document.write("<hl>Object Description</hl>"); objwindow.document.write("<p>"); objwindow.document.write("Book Title: " + this.title + "<br>");
Создание пользовательских объектов JavaScript Глава 11 objWindow.document.write ("Author: " + this, author + "<br>") ; objWindow.document.write("ISBNr " + this.ISBN + "<br>"); objWindow.document.write("Subject; " + this.subject + "<br>"); objWindow.document.write("Allen's Rating: " + this.rating + "<br>"); objWindow. document.write ("</bodyX/html>") ; objWindow.document.close(); II—> </script> Создание экземпляров Для задействования объекта, объявленного в конст- конструкторе book() необходимо создать его экземпляр. Для этих целей используется оператор new, синтаксис кото- которого выглядит так: окземллярОбъекта = new объектный Тип(параметр!, лараметр2, параметрЗ, ...) При помощи new объект Book создается следующим образом: dbBook = new book("Cost of Discipleship", "Dietrich Bonhoeffer", -57521-118-1", "Grace", 5) Теперь на это объект можно ссылаться из любого места кода через переменную (IBook. Экземпляр будет храниться в памяти, пока страница загружена в браузе- браузере. После перехода на следующую страницу или закры- закрытия браузера, экземпляр объекта исчезает. Присваивая значения свойствам объекта, не следует забывать об этом факте. Если требуется обеспечить постоянный объект, его обработка должна быть переложена на сторону сер- сервера. ПРИМЕЧАНИЕ """ ™Г' '" "" '*" Г**" ¦***"' '':f'[ *" '^' Постоянство, или устойчивость (persistence), - это весьма распространенное слово в предметной облас- области, связанной с объектами. В двух словах, это озна- означает способность создавать экземпляры объектов и сохранять состояние объектов так, что при следую- следующем доступе к объекту он восстанавливается в сохра- сохраненном состоянии. Клиентская часть JavaScript не обеспечивает свойства постоянства для объектов. В листинге 11.2 приведен код, реализующий созда- создание экземпляров объекта Book и вызывающий метод show(). На рис. 11.1 показан результат загрузки данной страницы в браузер. Листинг 112. Использование объектного конструктора Book. <html> ¦<head> <title>Using the book object</title> <script type""text/javascript"> function book(title, author, this.title = title; this.author = author; this. ISBN = ISBN; this, subject = subject; this.rating = rating; this . show = show ; ISBN, subject, rating) function show() { objWindow = window. open ("", "", "width=600 ,height=300") ; objWindow. document. write < "<htmlxbody>)"; objWindow.document.write ("<hl>Object Description</hl>") ; objWindow.document. write ("<p>" J.- objWindow. document, write ("Book Title: " + this.title + "<br>"); objWindow. document, write ("Author: " + this, author + "<br>") ; objWindow. document, write ("ISBN: " + this . ISBN + "<br>") ; objWindow. document.write ("Subject: " + this.subject + "<br>"); objWindow. document.write ("Allen's Rating: „ + this.rating + "<br>"); objWindow.document.write ("</body X/html>") ,- objWindow.document.close () ,• ]¦ </script> </head> <body>
Базовое подмножество языка JavaScript Часть II <script type="text/javascript"> <! — // Определение объекта Book dbBook = new book ("Cost of Discipleship" dbBook.show(); II—> </script> </bocly> </html> "'Dietrich Bonhoeffer", -57521-118-1", "Grace", 5) ,- Object Description Book. Title: Cost of Discipleship Author: Dl ISBN; 1-57521-118-1 abject: Grace Rich's Rating: 5 ¦<body> <hl>Book Objects</hl> <form name="forml"> <P> Select a book : РИСУНОК 11.1. Информация из объектаНооквыводится в новое окно Работа с экземплярами объектов Работу с экземпляром объекта можно продолжать сразу же после его создания — присваивать ему значе- значения или обращаться к любому из его методов. Кроме того, можно связать объекты с элементами пользова- пользовательского интерфейса. Например, требуется создать форму, которая бы позволяла изменять рейтинг книг и выводить на экран информацию для каждого созданного объекта Book. Объект Book можно определить так, как было показа- показано ранее, и создать пять его экземпляров: dbBook = new book(' sst of Discipleship", "Dietrich Bonhoeffer", 1-1", "Grace", 5) fkBook = new book ("The Once and Future King", "Т.Н. White", -57521-112-1", "Camelot", 5) olBook = new book ("On Liberty", "John Stuart Mill", -53221-118-1", "Political Philosophy", 4) ; iaBook = new book("Icarus Agenda", "Robert Ludlum", -53221-118-1", "Politcal Thriller", 2} cnBook = new took("Chronicles of Narnia", "C.S. Lewis", -53231-128-1", "Children's Fiction", 5) В самой форме следует использовать объект select с элементами <option>, определенными по одному для каждой книги, а также по одному на каждый показатель рейтинга (интервал от 1 до 5). Добавьте еще две кнопки - одну для установки рейтинга, а другую — для вывода на экран информационной формы по конкретной кни- книге. Код для реализации формы приводится ниже. Ре- Результат загрузки кода в браузер показан на рис. 11.2: <select name="bookList" size=l> <option value="dbBook">Cost of Discipleship</option> <option value="fkBook">The Once and •Future King</option> <option value="olBook">On Liberty </option> <option value="iaBook">Icarus Agenda </option> <option value="cnBook">Chronicles of Narnia</option> </select> Assign a rating: <select name="rating" size=l> <option>K/option> <option>2</option> <opt ion>3</opt ion> <option>4</option> <option>5</option> </select> Click to assign: <input type="button" name="Assign" value="Assign" onClick="assignRating() Click to show: <input type="button" name="Show" value="Show" onClick="showBook()" </form> </body> Сердце данного примера — это обработчик событий для кнопок Assign и Show. Метод assignRating() присва- присваивает книге выбранное значение рейтинга: function assignRating {) { selectedBook = document.forml.bookList. options[document, forml. ^•bookList. selectedlndexJ . value;
Создание пользовательских объектов JavaScript selectedBook = eval(selectedBook); selectedBook.rating = document.forml.rating.options[document.forml. *• rating, selectedlndex] .text; Book Objects Setetabod- Assign a rating: ra Clbktoasslg-i: РИСУНОК 11.2 Форма i i Book. Посмотрев внимательнее на код, несложно заметить, что метод получает значение выбранной опции bookList и присваивает его переменной selectedBook. Для полу- получения этого значения используется свойство options Листинг 11.3. Исходный код для примера showBook(). Глава 11 объекта bookList вместе с его же свойством selectedlndex. Сейчас имя объекта Book содержится в переменной selectedBook, однако JavaScript воспринимает его как строковое значение, а вовсе не как ссылку на экземп- экземпляр объекта. Поэтому для преобразования переменной в объектную ссылку используется метод eval(). В последней строке метода свойству rating перемен- переменной selectedBook присваивается значение вновь выбран- выбранного рейтинга, содержащееся в объекте ratingSelect. ПРИМЕЧАНИЕ Для проверки типа переменной во время выполнения метода можно использовать оператор typeof. Напри- Например, следующий код отображает окно сообщений, вы- выводящее тип переменной selectedBook: alert(typeof selectedBook); Метод showBook() использует ту же технологию для вызова метода объекта show(): function showBook(> { selectedBook = document.forml.bookList. "->options [document, forml.bookList.selectedlndex].value; selectedBook = eval(selectedBook); selectedBook.show() ; Листинг 11.3 содержит полный исходный код дан- данного примера. <html> <head> <^1Ые>Использование объекта Book</title> <script type="text/javascript"> subject, rating) function book(title, author, ISBN, this.title = title; this.author = author; this. ISBN = ISBN; this.subject = subject; this.rating = rating; this.show = show; I function show ( ) {, objWindow = window . open ("", "", "width=600 ,height=300") ; objWindow. document, write ( "<htmlxbody;)"; objWindow. document, write ("<hl>Object Description</hl>") ; objWindow. document .write("<p>") ; 1 + this.title + "<br>"); 1 + this.author + "<br>"); objWindow. document, write ("ISBN: " + this . ISBN + "<br>") ; ' + this.subject + "<br>"); objWindow.document, write ("Allen's Rating: ' + this, rating + "<br>"), objWindow. document.write ("</body X/html>") ; ob jwindow document. close( ) ; function assignRating() { selectedBook = document, forml .bookList.options [document.forml.bookList. selectedlndex] .value; selectedBook = eval(selectedBook); selectedBook. rating = document, forml. rating, options [document.forml .rating, selectedlndex] . text;
Базовое подмножествоязыка JavaScript Часть II function showBook() { seleetedBook = document.forml.bookList.options[document.forml.bookList.selectedlndex].value; selectedBook = eval (seleetedBook) ; seleetedBook.show (); I // Вьпожить во время загрузки dbBook = new book("Cost of Discipleship", "Dietrich .fkBook = new book("The Once and Future King", "Т.Н.. olBook = new book("On Liberty", "John Stuart Mill", iaBook = new book ("Icarus Agenda", "Robert Ludlum", Bonhoeffer", -57521-118-1", "Grace", 5} White", -57521-112-1", "Camelot", 5) ; -53221-118-1", "Political Philosophy", -53221-118-1", "Political Thriller", 3) cnBook 1= new book("Chronicles of Narnia" , "C.S. Lewis", -53231-128-1", "Children1s Fiction", 5) , </script> </head> <body> <hl>Book Objects</hl> <?orm name=" forml"> <P> Select a book: select name="bookList" size=l> <option value="dbBook">Cost of Discipleship</option> <option value="fkBook">The Once and Future King</option> <option <option <option elect> value="olBook">On Liberty</option> value="iaBook">Icarus Agenda</option> value="cnBook">Chronicles of Narnia</option> Assign a rating: <select name="rating" size=l> <opt ion>l</opt ion> <option>2</option> <option>3</option> <opt ion>4</opt ion> <option>5</option> </select> Click to assign : <input type="button" name="Assign" value="Assign" onClick="assignKating() Click to show: <input type="button" name="Show" value="Show" onClick="showBook() </form> </body> </html> Создание составных объектов Объекты, с которыми мы имели дело до этого момен- момента, относятся к категории простых объектов. Они обла- обладают одним уровнем свойств и методов. Следующий пример, посвященный созданию объекта buttonSet, с одной стороны более быстр, а с другой — более сложен в восприятии. Разрабатываемый объект должен позво- позволять "на лету" добавлять кнопки в соответствующий массив, помещать buttonSet в любой объект Document и по заданным условиям отображать отдельные кноп- кнопки. Конструктор объекта buttonSet показан в листинге 11.4.
Создание пользовательских объектов JavaScript Глава 11 Листинг 11.4. Конструктор объекта buttonSet. <soript type="text/javascript"> << function buttonSet (name) { this, name = name; this, length = 0; this.addBtn = addBtn; this.print = print; // Указать, куда Б объект поместить дополнительные элементы. // Любое выполненное изменение отразите в this.print(). this.index = 4; return this ; ,// Метод print() объекта buttonSet function print(dObj) { var spacelnt; for (var i = 5; this. index >= i; i++) { if(eval(this[i].condition)) { dob j .writeln('<a href=" '+this [i] .url+' "Ximg src='" + this [i] .file+'" alt=" '+this[i] .alt + 111 width=4" height=6" border=0X/a>') ; // Если требуется, добавляем пробелы spacelnt = 0 + this[i].spacer; if(navigator.appName = "Microsoft Internet Explorer") { spacelnt = spacelnt + 3 ; i if (spacelnt != 0) { dobj.write('<img src="images/space.gif" width=' + spacelnt + 'height=46 border=0>'); </script> Помимо прочих, JavaScript поддерживает составные объекты, свойства которых сами могут быть объектами. Составные объекты дают возможность более логично структурировать код. Это гораздо лучше, нежели пы- пытаться втиснуть все данные в одноуровневый объект. Предположим, что требуется отслеживать информа- информацию о сотрудниках, их текущих проектах и клиентах. Очевидно, что адрес клиента не должен быть частью описания объекта сотрудника. В этом смысле суще- существенную помошь в структуризации данных вокруг трех отдельных, однако связанных сущностей — сотрудник, проект, клиент — окажут составные объекты JavaScript. В конструкторе employee определите основные свой- свойства (имя, телефон, адрес электронной почты) и метод showSummarylnfoQ. Для представления связанной с Проектом информации потребуется определить свойство project в объекте employee. Определение выполняется таким же путем, как и для обычного свойства, за исклю- исключением того, что параметр project является ссылкой на другой объект, а не на строковое значение: function employee(FirstName, LastName, HomePhone, Ext, EmailAddress, project) ( this.FirstName = FirstName; this. LastName = LastName; this.HomePhone = HomePhone; this.Ext = Ext; this.EmailAddress = EmailAddress; this.Project = project; this . showSummarylnf о = summarylnf о; i Совершенно аналогично определите объект project, установив объект client в качестве свойства: function project(ProjectName, client, DevTool) { this.ProjectName = ProjectName; this.Client = client; this.DevTool = DevTool; "j function client(ClientName, Address, City, State, Zip) { this.ClientName = ClientName; this. Addre s s = Addre s s; this.City = City; this.State = State; this. Zip = Zip; } Создаваемый сейчас метод showSummaryInfo() де- демонстрирует способ ссылки на эти вложенные объекты. Функциональность этого метода связана с отображения нового окна для представления краткой информации о сотруднике — список всех свойств объекта employee и других объектов внутри него.
Базовое подмножество языка JavaScript Часть II function summaryInfo() { objwindow = window.open("", "", "width=600,height=400"); ob jwindow. document. write ("<htmlxbody>"); objwindow.document.write("<hl>Employee Summary Information Sheet </hl>"); objwindow.document.write("<h2>" + this.FirstName + " " + this.LastName + "</h2>"); objwindow. document.write ('<<pXemXSstrong>Contact Information </strong></emX/p>") ; objwindow.document.write("<p>Home Phone: " + this.HomePhone + "</p>"); objwindow.document.write("<p>Ext. : " + this.Ext + "</p>"); objWindow.document.write("<p>Email: " + this.EmailAddress + "</p>"); objwindow. document .write ("<pXemXstrong>Pro ject Information </strongX/emX/p>") ; objwindow.document.write ("<p>Current Project: " + this .project.ProjectName + "</p>"); objwindow.document.write("<p>Client: " +¦ this.Project.Client.ClientName + "</p>") ; objwindow. document.write("<p>Client: " + this.Project.Client.Address + "</p>"); objwindow.document.write("<p>Client: " + this. Project. Client. City + ", " + this. Pro ject. Client. State + " " + this.Project.Client.zip + "</p>">; objwindow.document.write("<p>Developmnt Tool Used: " + this.Project.DevTool + "</p>"); objwindow.document.write("</bodyX/html>") ; objwindow.document.close(); Ссьшка на дочерний объект выполняется в соответ- соответствие с точечной нотацией. Таким образом, на адрес кли- клиента можно сослаться через this.Project.CIient.Address. Точечная нотация позволяет легко и просто отследить код с момента определения пути для используемых методов и свойств, поскольку предполагает указание пути к тому или иному методу либо свойству. Совер- Совершенно несложно добраться до родительских объектов (имена которых находятся слева перед первой точкой), проходя через множество дочерних до тех пор, пока не встретится искомый метод или свойство. Как только определены конструкторы для каждого из объектных типов, приступайте к созданию экземп- экземпляров employee, project и client. CoastTech = new client("Coastal Techonology", 00 Beacon Hill", "Boston", "MA", 1220") ; Coastal = new project("CoastalOl", CoastTech, 11 JavaScript") ; Allen = new employee("Allen", "Wyke", 17/555- '212", 00", "allen@anywhere.com", "Coastal"); Параметр project в определении объекта сотрудни- сотрудника и параметр client в определении объекта проекта - далеко не строки; они — суть имена вновь созданных объектов. Обязательно примите во внимание порядок создания объектов. Поскольку объект Allen использует объект проекта Coastal в качестве параметра, создание экземпляра Coastal должно происходить в первую оче- очередь, иначе возникнет ошибка. По тем же соображени- соображениям, сначала потребуется создать экземпляр CoastTech объекта client и только затем заняться созданием про- проекта Coastal. После создания экземпляров объектов обратитесь к Allen.showSummaryInfo() для отображения окна, пока- показанного на рис. 11.3. В листинге 11.5 показан исходный код для этого примера. Employee Summary Information Sheet Thelma Turner Contact Information ¦ Home Phore: 556-2364J02 Ext: 100 Email; thelma@ibjrner.com Project Information Current Project; CoastalOl - : Client Coastal Techonology Address: lOOBeacon Hill City, State, Zip: Boston, MA 01220 Development Tool Used: JavaScript РИСУНОК 11.3. Страница с краткой информацией о сотруднике. Листинг 11.5. Пример использования объектов employee, client и project. <html> ¦<head> <title>Using the book object</title> <script type="text/javascript">- function employee (FirstName, LastName, HomePhone, this.FirstName = FirstName; Ext, EmailAddress, project) {
Создание пользовательских объектов JavaScript Глава 11 this, LastName = LastName; this. Home Phone = HomePhone; this. Ext == Ext; this.EmailAddress = EmailAddress; this.Project = project; this.showSummarylnfо = summarylnfо; function summarylnfо() { objWindow = window.open("", "", "width=600,height=400"> ; objWindow. document. write ("<htmlxbody>") ; ObjWindow.document.write("<hl>Employee Summary Information Sheet</hl>"); objWindow.document.write("<h2>" + this.FirstName + " " + this.LastName + "</h2>"); objWindow.document.write ("<pXemXSstrong>Contact Information</strongX/emX/p>") ; objWindow.document.write("<p>Home Phone: " + this,HomePhone + "</p>"); objWindow.document.write("<p>Ext.: " + this,Ext + "</p>"); objWindow.document.write("<p>Email: " + this.EmailAddress + "</p>") ,• objWindow. document, write ("<pXemXstrong>ProjectInformation</strongX/emX/p>") ; objWindow.document.write("<p>Current Project: ' + this.project.ProjectName + "</p>"); objWindow.document.write ("<p>Client: " + this.Project.Client.ClientName + "</p>"); objWindow.document.write("<p>Clientr " + this.Project.Client.Address + "</p>"); ob jWindow. document, write ("<p>Client: "¦ + this.Project.Client.City + ", " + this.Project.Client.State + " " + this.Project.Client.zip + "</p>") ; objWindow.document.write("<p>Development Tool Used: " + this.Project.DevTool + "</p>"); objWindow.document.write ("</bodyX/html>") ; objWindow.document.close() ; function project (ProjectName, client, this. ProjectName = ProjectName; this.Client = client; this. DevTool = DevTool ; DevTool) ( City, State, Zip) { function client(ClientName, Address, this . ClientName = ClientName; this.Address = Address; this. City = City; this.State - State; this. Zip = Zip; j II—> </script> </head> <body> <script type="text/javascript"> CoastTech = new client ("Coastal Techonology" , 00 Beacon Hill", "Boston", "MA", 1220"); Coastal = new project ("CoastalOl", CoastTech, "JavaScript") ; Allen = new employee ("Allen", "Wyke", 17/555-1212", 00", "allen@anywhere.com", "Coastal"), Allen. showSummarylnf о (У; //—> </script> </body> </html> Динамическое создание объектов Возможность создания объектов непосредственно в коде существенно расширяет возможности разработчика. Во всех рассмотренных ранее примерах объекты создава- создавались посредством оператора new во время загрузки окна. А какие же действия потребуется предпринять для со- создания объектов во время выполнения? Объектно-ори- Объектно-ориентированные среды программирования позволяют со- создавать экземпляры "на лету". JavaScript позволяет создавать объекты "на лету", ¦однако все же с рядом определенных ограничений. Сначала планировалось создать обобщенную функцию, которая бы создавала экземпляры при каждом ее вызо- вызове. Если замысел увенчается успехом, исчезнет необхо- необходимость в использовании операторов new, и объекты
Базовое подмножество языка JavaScript Часть II можно будет создавать на основе информации, введен- введенной пользователем. Идея метода выглядит приблизи- приблизительно так: function addEmployee(ObjectName,FirstName, LastName) { ObjectName = new employee(FirstName, LastName); ) В идеальном случае метод должен был создавать экземпляр объекта и присваивать ему имя на основе значения параметра ObjectName. К сожалению, попыт- попытка успехом не увенчалась. JavaScript не позволяет име- имени экземпляра объекта быть переменным. Вместо этого в качестве имени объекта используется ObjectName. На- Например, если Frank определен как объектная ссылка, то следующее выражение будет полностью корректным: function addFrank(FirstName, LastName) ( Frank = new employee(FirstName, LastName); ) Несмотря на невозможность динамического имено- именования реализованных объектов, объект можно создать как элемент массива-контейнера. Это означает, что мож- можно предусмотреть массив employeeList, который будет хранить все созданные объекты employee. Таким обра- образом, можно изменить метод addEmployee(), использовав вместо него что-то наподобие: function addEmployeeObject(FirstName, LastName, HomePhone, Ext, EmailAddress) { Листинг 11.6. Динамическое создание объектов. empList[i] = new employee (FirstName LastName, HomePhone, Ext, «mailAddress); .Используя приведенный выше метод, можно созда- создавать экземпляры объектов, базируясь на вводе пользо- пользователя и динамическом создании объекта за счет вызо- вызова addEmployeeObject(). Например, при помощи формы, представленной на рис. 11.4, пользователь может вво- вводить основную информацию о сотрудниках. После щел- щелчка на кнопке Add создается новый экземпляр объекта. В листинге 11.6 показан исходный код для данной формы. Dynamic Object Creator РИСУНОК i 1А Динамическое создание объектов. <html> <head> <title>Intranet Employee Database</title> <script type="text/javascript"> < ! — // Глобальные переменные var i = 0; // Создание массива var empList = new Array () ; .// Конструктор объекта сотрудника function employee (FirstName, LastName, HomePhone, Ext, EmailAddress) ( this.FirstName = FirstName; this. LastName = LastName; this.HomePhone = HomePhone; this.Ext = Ext; this. EmailAddress = EmailAddress; this . show = show; function show ( > { alert (this. FirstName + "/n" + this. LastName + "/n" + this.HomePhone + "/n" + this. Ext + "/n" + this. EmailAddress) ; function addEmployeeObject (FirstName, LastName, HomePhone, Ext, EmailAddress) { empList[i] =» new employee (FirstName, LastName, HomePhone, Ext, EmailAddress); function insertRec >rd() { FirstName = document.forml.FirstName.value;
Создание пользовательских объектов JavaScript Глава 11 LastName = document.forml.LastName.value; HomePhone = document. forml. HomePhone. value; Ext = document, forml.Ext.value; EmailAddress = document.forml.EmailAddress.value; addEmployeeObject(FirstName, LastName, HomePhone, Ext, EmailAddress) ; ) function showAll() { objWindow = window. open ("", "", "width=600,height=300"); objWindow. document. write ("<htmlxbody>" ); objWindow.document.write("<hl>Object Description</hl>"); objWindow.document.write("<p>"); for (var q=l; q<empList. length; q++) { objWindow.document.write("<strong>" + empList[q].FirstName + " " + empList[q] .LastName + "</strongX/p>") ; objWindow.document.write("<p>" + empList[q] .HomePhone + "</p>") ; objWindow.document.write("<p>" + empList[q].Ext + "</p>"); ob jWindow. document, write ("<p>" + empList[q] .EmailAddress + "</p>"); objWindow. document. write ("</bodyX/html>") ; objWindow.document. close () .11—> </script> </head> <body> <hl>Dyanamic Object Creator</hl> <p>Enter employee information in the form below and click the Add button. Press the Show All button to view a list of all employees you have entered.</p> <form name="forml"> <pre> First Name: <input type=text size=20 maxlength=256 name="FirstName"> </pre> <pre> Last Name: ¦<input type=text size=20 maxlength=256 name="LastName"> </pre> <pre> Home Phone: <input type=text size=20 maxlength=256 name="HomePhone"> </pre> <pre> Ext. : <input type=text size=20 maxlength=256 name="Ext"> </pre> . <pre> Emai 1 Addr e s s: <input type=text size=20 maxlength=256 name="EmailAddress"> </pre> <pre> <input type="button" name="Add" value="Add" onClick="insertRecord()"> <input type="button" name="ShowAll" value="Show All" onClick="showAll()"> </'pre> </form> </body> </html> Кнопка Show All (Показать всех) позволяет просмот- ПРИМЕЧАНИЕ .,,-._ ¦ ¦ , ;. "¦ ': ' »" реть все объекты, созданные в течение сеанса. На рис. Объекты типа массивов не поддерживались Netscape 11.5 показан список объектов employee, экземпляры ко- Navigator вплоть до его версии 3.0. Учтите это при со- ТОрЫХ уже были созданы. здании сценариев для версии 2.0. 6 I-IS8
Базовое подмножество языка JavaScript Часть II Object Description Tom Smith 555-1221 129 tom@rnv.com Tim Smith 555-1222 1» tim@mv.cwn Leon Openhlemer 111-1112 132 1eon@my.com s :; i: j. Л in ¦••¦ - РИСУНОК 11.5. Список созданных динамически объектов. Расширение экземпляров объектов Раз уж JavaScript является слабо типизированным язы- языком, он весьма гибок в плане описания объектов. Оп- Определение экземпляра любого объекта можно расши- расширить, объявив новое свойство и присвоив ему значение. В качестве примера добавим в экземпляр cnBook объекта Book из предыдущей главы свойство Series. Экземпляр cnBook создается следующим образом: cnBook = new book("Chronicles of Narnia", '-Lewis", -53231-128-1", "Children's Fiction", 5) ; Где-то в сценарии поместите код добавления свой- свойства Series: cnBook.Series "True" Подобная технология применима только к экземп- экземплярам объектов, но не к объектному типу. С другой стороны, браузеры, поддерживающие как минимум JavaScript 1.1. позволяют расширять созданные объек- объекты с использованием объектных прототипов, синтаксис которых выглядит так: Объектный прототип позволяет добавлять свойства и методы к каждому экземпляру объектного типа. Если бы требовалось к каждому объекту Book добавить но- новое свойство recommended со значением true, следовало бы воспользоваться кодом, показанным ниже: book.prototype.recommended = True; Протестировать все можно, вызвав alert(cnBook. recommended). Результат тестирования показан на рис. 11.6. РИСУНОК 11.6. Вывод на экран значения свойства с использованием alert(). Резюме JavaScript поддерживает возможность создания пользо- пользовательских объектов в клиентских сценариях, что делает язык более гибким и позволяет структурировать код в соответствие с объектно-ориентированной методологи- методологией. В главе были рассмотрены различные аспекты созда- создания и реализации объектных типов. Читатели почерп- почерпнули информацию о том, как можно расширить функ- функциональность обычных объектов за счет создания составных объектов, т.е. того, что носит название "объектов внутри других объектов". Составные объекты используются для инкапсуляции данных, простираю- простирающихся на большое количество уровней. По аналогично- аналогичному же принципу строятся реляционные базы данных с отношениями "один-ко-многим". В добавок ко всему, читатели узнали о расширении экземпляров объектов с использованием прототипов объектов. объектныйТип.prototype.имяСвойства;
Серверная часть JavaScript В ЭТОЙ ГЛАВЕ Использование архитектуры клиент/сервер Разработка серверных приложений JavaScript Базовые серверные объекты Несмотря на то что JavaScript играет ключевую роль именно со стороны клиента, зачастую этот язык про- программирования используется при создании серверных приложений (с помощью Netscape Server-Side JavaScript, SSJS). SSJS, как и его эквивалент для клиентской сто- стороны, представляет собой набор объектов, функций и методов, расширяющих стандарт ECMAScript. Примени- Применительно к разработке Web-приложений, он использует- используется в качестве серверного языка сценариев, заменяюще- заменяющего CGI и другие технологии. ЁПРИМЕЧАНИЕ ^ Оригинальное название серверной части JavaScript выг- выглядит как LiveWire. Начиная с Netscape Enterprise Server 3, LiveWire был погружен в сервер, после чего пере- перестал существовать в виде отдельного продукта. LiveWire на данный момент реализует функциональность подклю- подключения к базам данных. ПРИМЕЧАНИЕ SSJS работает только на Netscape-серверах, поэтому в настоящий момент нельзя использовать с другими Web- серверами. Компания Microsoft поддерживает JScript в собственном сервере Active Server Pages (ASP), одна- однако эти расширения серверного языка отличаются от SSJS. И вообще, не стоит забывать, что Java Server Pages (JSP) — это совершенно другая технология. Прежде чем углубиться в SSJS, необходимо разоб- разобраться, как создавать приложения типа сервер/клиент. SSJS вместе с используемым для управления этими при- приложениями менеджером приложений (Application Manager) в клиент-серверной модели представляют сер- сервер. Клиентом является браузер или приложение, куда отправляется информация. Изучение технологии кли- клиент/сервер существенно повысит уровень ваших знаний. Использование архитектуры клиент/ сервер Клиент и сервер представляют собой различные сущно- сущности, независимые друг от друга до тех пор, пока клиен- клиенту не понадобится информация от сервера. Концепция клиент/сервер усовершенствовалась до такой степени, что вышла за пределы сервера, служившего просто хос- хостом для HTML-страниц. Серверная часть Web-прило- Web-приложения может быть истинным сервером, поддерживаю- поддерживающим обработку приложения и хранение баз данных. Хранение обычных статических документов кануло в лету. Web-приложения с клиент-серверной архитектурой Разработка Web-приложений типа клиент/сервер отли- отличается от традиционного процесса разработки в рамках архитектуры клиент/сервер. Так сложилось, что сервер рассматривается в качестве разновидности сервера баз данных, используемого для хранения и обработки зап- запросов данных от клиента. В клиент-серверной техноло- технологии для Web сервер не обязательно должен быть базой данных, это просто Web-сервер, используемый для об- обработки, администрирования и выполнения вычислений в HTML-документах. Все еще существует возможность разделения функциональности между клиентом и сер- сервером, тем не менее, обработка централизована на сер- сервере. Двухуровневая структура приложений Разрабатываемое приложение необходимо разбить на две четко определенных части. Это как раз и есть дву-
Базовое подмножество языка JavaScript Часть II хуровневая структура для архитектуры типа клиент/сер- клиент/сервер. Первая часть представляет собой пользовательский интерфейс (UI), или внешний интерфейс, который обеспечивает связь пользователя с приложением. Вто- Вторая часть — сервер, где проходит основной процесс выполнения. Благодаря наличию клиентской части JavaScript, выполнение можно разделить между клиен- клиентом и сервером в соответствии с требованиями прило- приложения. В обычной среде было бы разумнее перенести как можно большую часть обработки на клиентскую часть, поскольку необходимо располагать определенной сте- степенью управления конфигурацией и настройкой машин пользователей. Такое разделение может сделать сам раз- разработчик, по своему усмотрению, в зависимости от воз- возможностей клиентской стороны, загрузки сервера и се- сетевого трафика. Сервер — это обрабатывающий механизм приложе- приложений. Он управляет и хранит большое количество дан- данных, выполняет интенсивные и крупномасштабные вы- вычисления, а также системную обработку. Возможность изоляции двух частей системы, обес- обеспечивающая их независимость друг от друга, внесли существенную долю в развитие широкомасштабных систем баз данных. Упомянутая возможность привносит дополнительную гибкость в процесс разработки при- приложений. N-уровневая структура приложений Л^-уровневая методология применяется с целью преодо- преодоления ограничений двухуровневой структуры. УУ-уров- невая архитектура предусматривает разбиение пользо- пользовательского интерфейса, обработки и хранения данных на отдельные уровни, еще больше разделяя рабочий поток. Клиент отвечает за пользовательский интерфейс и несложную обработку, а сервер — за хранение дан- данных. При этом существенная обработка и вычисления (или бизнес-правила) перемещаются на средний уровень. Такие возможности позволяют вносить изменения в бизнес-правила, не оказывая влияния на пользователь- пользовательский интерфейс и базы данных. По сравнению с обычной средой приложений, в сре- среде Web-разработки клиентский компьютер (и Web-бра- Web-браузер, и рабочая станция) управляется в гораздо меньшей степени. Очень сложно оценить, как проходят процессы на клиентской части. Более разумно запускать процес- процессы на серверной части, потому как необходимо конт- контролировать среду, обеспечивая тем самым предсказуе- предсказуемые результаты. С другой стороны, обычные приложения типа кли- клиент/сервер сталкиваются с некоторыми проблемами, незнакомыми для клиент-серверных Web-приложений. В обычных приложениях баз данных типа клиент/сер- клиент/сервер при изменении клиентского модуля повторное рас- распределение целого приложения не требуется, посколь- поскольку клиентом является Web-страница и модификации распространяются автоматически при ее следующей заг- загрузке. Браузер инициирует транзакцию путем отправки серверу запросов на выполнение некоторых операций, на получение информации из баз данных, на определен- определенные вычисления, на запуск процессов либо на выпол- выполнение функций SSJS. Прежде чем продолжать, клиент должен дождаться ответа от сервера. Процессы сервер- серверной части обеспечивают хранение кода в едином цен- централизованном сервере. Это позволяет более быстро выполнять требуемые модификации и увеличивает ско- скорость прохождения процессов, поскольку все они вы- выполняются на сервере. Как не попасть в западню С использованием JavaScript связан ряд вопросов каса- касаемо архитектуры типа клиент/сервер. В зависимости от предпочтений, обработка в JavaScript может распреде- распределяться между клиентом и сервером. Скорость обработ- обработки со стороны клиента зависит от клиентской среды, памяти, быстродействия и других внутренних факто- факторов, в то время как на сервере скорость зависит от тра- трафика в Internet и запущенных процессов на сервере. В этой связи неплохой идеей будет разделение обработ- обработки между различными элементами с акцентированием внимания на сервере, как на более известной и предска- предсказуемой сущности. »примечание! . " v; ;!; Размышляя над дизайном архитектуры на ранних стади- стадиях разработки Web-приложений, можно создавать бо- более устойчивые приложения, что ускорит выполнение процессов. Передача информации между клиентом и сервером Связь клиента с сервером в Web-среде — очень важный вопрос, которому стоит уделить особое внимание. В отличие от клиент-серверной среды в обычных сетях, Web-среда не обеспечивает постоянной связи с серве- сервером, устанавливая вместо этого взаимодействие через протоколы HTTP с использованием TCP/IP. От клиента к серверу Самый важный обмен информацией между клиентом (браузером) и сервером — это клиентские запросы. Сама природа HTTP требует, чтобы браузер клиента отправ- отправлял на сервер запросы на любую необходимую инфор- информацию. Сервер не может самостоятельно инициировать переход или подключение к HTTP-документу.
Серверная часть JavaScript Формат HTTP-запроса к серверу может быть базо- базовым запросом HTML-страницы или запросом, включа- включающим информацию содержимого либо данные, кото- которые должны быть обработаны или отправлены на сервер. К тому же, часть информации, содержащаяся в запросе (называемая "телом"), включает в себя данные (содержимое) функций или полей HTML-документа, с которыми будет работать сервер. HTTP-запросе содержит три основных группы ин- информации: ¦ • Строка запроса (GET, HEAD, POST), URL и версия HTTP. Пары имя/значение для таких полей, как accept, refer, if-modifled, user-agent, content-type, content- length. • Содержимое — информация (данные), отправленная на сервер для обработки. От сервера клиенту После отправки клиентом на сервер запроса определен- определенной информации, сервер, в свою очередь, отправляет клиенту сообщение, содержащее запрашиваемую инфор- информацию. HTTP-ответы обладают тем же форматом, од- однако в конце содержат возвращаемый HTML-документ (ответ). HTTP-ответ содержит три основных группы инфор- информации: ¦• Строка ответа • Заголовки ответа ¦• Данные ответа Серверная строка ответа имеет синтаксис версии HTTP, код состояния (код возврата из трех цифр) и строку ответа текста (не используемую браузером, но участвующую в интерпретации документа). Все сказан- сказанное выглядит следующим образом: НТТР/1.1 200 ОК Server: Netscape-Enterprise/3.5.1G Date: Wed, 19 Apr 2000 17:13:33 GMT Content-type: text/html Connection: close Строка ответа предоставляет браузеру начальную информацию о том, что можно ожидать далее, если пройти ответ до самого конца. Версия HTTP сообщает о том, как начать интерпретацию документальной час- части ответа, а код состояния — что можно ожидать пос- после возврата. Например, код состояния ответа, равный 200, означает "ОК" (то бишь, "все будет хорошо"). Iпримечание ., '..; ,.^, :а,>„,-, . ¦'¦¦{}' Существует великое множество кодов ответа (наподо- (наподобие 200, 302, 404), которые имеют отношение к состо- состоянию и возвращаемому содержимомудокумента. Глава 12 Данные ответа, или "тело", — это последняя часть HTTP-ответа. Они хранятся в формате, определенном content-type. Значение этих данных зависит от кода со- состояния, возвращаемого в заголовке ответа. Как прави- правило, данные ответа имеют форму HTML-документа, ко- который и будет отображаться в браузере клиента. Управление сеансами Одно из преимуществ Web и технологии разработки Web-приложений в то же время является и существен- существенным препятствием для приложений, требующих взаи- взаимодействия клиента и сервера. Поскольку сервер опе- оперирует в среде, не поддерживающей концепцию состояний, выполнение происходит гораздо быстрее, однако при этом сервер должен полностью полагаться на клиента в том плане, что клиент сам должен напо- напоминать, кто он есть и когда он производит запрос. Эво- Эволюция HTML от статических страниц к интерактивным приложениям повлияла на среды, не обладающие состо- состоянием, заставив искать способы осуществления поддер- поддержки состояния. Поскольку клиент не связан постоянно с Web-сер- Web-сервером, возникает немаловажная проблема: как сообщить Web-серверу, кто является клиентом при его повторном подключении к серверу и отправке запроса. Если бы подключение Web-приложений к серверу было бы по- постоянным, то разработка Web-приложений была бы столь же простой, как и разработка приложений типа клиент/сервер. Существует несколько методов управления сеанса- сеансами, среди которых — использование клиентских cookie- наборов, кодирование URL и IP-адреса на сервере. Пер- Первых две технологии предполагают полную поддержку состояния со стороны клиента и определенную помощь со стороны сервера. В случае технологии, связанной с IP-адресами, поддержку информации осуществляет сер- сервер, а клиент лишь оказывает в этом помощь. Cookie-наборы Cookie-наборы обеспечивают механизм сохранения кли- клиентской информации на Web-сервере, предусматрива- предусматривающий идентификацию. Эта информация может быть использована в будущих подключениях к серверу. Cookie-наборы — это методология поддержки состоя- состояния клиентов. Сервер сохраняет информацию о клиен- клиенте на клиентской части, а затем клиент отправляет со- сохраненную информацию обратно на сервер вместе с каждым HTTP-запросом. Cookie-наборы хранятся в текстовом файле на кли- клиентском дисковом устройстве. Сервер, как средство от- отслеживания состояний клиентов, может помещать ин- информацию в cookie-набор столько раз, сколько это позволяет браузер. Различные браузеры по-разному рабо- работают с cookie-наборами. Некоторые (скажем, Navigator)
Базовое подмножество языка JavaScript Часть II имеют только один файл cookie, в который все сервера записывают информацию, помечая его разделы специ- специальными именами URL по мере сохранения и обновле- обновления. Другие браузеры, такие как Internet Explorer, сохра- сохраняют информацию в различных файлах каталога cookie. ^ПРЕДУПРЕЖДЕНИЕ : '¦''¦:- ^ V '$.¦ Размер файла cookie ограничен. Передаваться клиенту и сохраняться на его стороне может только определен- определенный объем информации. Сей факт ограничивает коли- количество информации, которую может сохранять каждый сервер, и число Web-серверов, сохраняющих информа- информацию на клиентском компьютере. Всегда существует вероятность ошибочного удале- удаления файла cookie (это всего лишь текстовый файл). В этом случае сервер потеряет информацию о состоянии, поэтому клиенту для стабилизации своих отношений с сервером придется все начать сначала. Поскольку cookie-информация хранится на клиен- клиентской части, то серверные элементы повлиять на нее не могут. Это позволяет клиенту выполнить повторную от- отправку запроса, даже если первый раз на сервере возни- возникали какие-то проблемы. Другое преимущество cookies- наборов заключается в том, что сервер не обязан хранить информацию о клиенте; после первоначально- первоначального запроса информации сервер вообще может "забыть" о клиенте. Cookie-наборы приводят к увеличению трафика, поскольку с каждым запросом сервер должен отправлять и получать дополнительную информацию. Cookie-ин- Cookie-информация передается в соответствие с методологией пар имя/значение, используя для этого протокол передачи cookie-информации. Кодирование URL Кодирование клиентского URL для поддержки инфор- информации о состоянии взаимодействия клиент-сервер пре- предусматривает отправку пары имя/значение (name/value) или уникальных ключевых полей информации как ча- части строки URL в клиентском HTTP-запрос. Подобный способ сохранения информации о состоянии выгоден для серверов так же как и cookie-наборы, поскольку в данном случае серверы не должны сохранять какую- либо информацию. V.ПРИМЕЧАНИЕ ''"*? - ' J: Использование данного процесса для поддержки клиен- клиентского состояния требует, чтобы построение URL было динамическим каждый раз, когда генерируется запрос, Разумеется, размеры URL при этом существенно воз- возрастают. Использование метода кодирования клиентских URL обеспечивает значительную гибкость, если суще- существует потребность в поддержке состояния. В отличие от cookie-наборов, кодирование URL не зависит от кон- конкретного браузера. Поскольку разработчик не ведает, какой конкретно браузер получает доступ к серверу, то это, пожалуй, наилучший способ поддержки состояния. IP-адреса на сервере Третий способ поддержки состояния — сохранение IP- адреса и информации о состоянии на сервере. Это оз- означает, что сервер должен иметь доступ к базам данных или к совместно используемой памяти, где будет сохра- сохраняться информация. Хранение информации о сос- состоянии основано на IP-адресах клиента. Информация используется и хранится только совершенно определен- определенным сервером. Из-за множества недостатков, такой способ поддер- поддержки состояния используется только в определенных случаях: Должно быть известно, что клиенты обладают посто- постоянными IP-адресами Приложение поддерживает только один сервер Практика динамического распределения IP-адресов для машин, которые выполняют Web-браузеры, делает невозможным внедрение данного способа хранения со- состояния. Кроме того, невозможна также и поддержка множества Web-серверов. Разработка серверных приложений JavaScript После того как все особенности серверной части языка JavaScript рассмотрены, можно приступить к исследо- исследованию процесса разработки приложений в этой среде с использованием SSJS. На рис. 12.1 показаны все дета- детали упомянутого процесса. Создание исходных файлов Первый шаг к построению серверного приложения JavaScript связан созданием исходных файлов, которые бывают двух видов: Исходные HTML-документы. Эти документы могут быть статическими либо страницами с кодами JavaScript. Их расширения — .htm или .html. • Библиотечные файлы JavaScript. Их расширение - js. Эти файлы служат в качестве библиотек функций JavaScript. Использовать HTML-дескрипторы внут- внутри них не требуется.
Серверная часть JavaScript Создание исходных HTML- и JS-файлов Компиляция е приложение .WEB РИСУНОК 12.1. Процесс разработки серверных приложений JavaScript. Установка в виде серверного расшк- рения LiveWIre Server Extension Запуск приложения из LiveWire Application Manager Рассмотренные файлы необходимы, поскольку, в отличие от клиентской части JavaScript, до помещения на Web-сервер SSJS следует откомпилировать в байтко- ды. Упомянутая необходимость предварительной ком- компиляции рассматривается с одной стороны как досто- достоинство, а с другой — как недостаток использования JavaScript на серверной части. Достоинство заключает- заключается в том, что именно по причине предварительной компиляции операция выполнение существенно уско- ускоряется. Однако, одновременно, это же и недостаток, по- поскольку большая часть того, что создается в SSJS, дол- должно быть обязательно Wcb-приложениями, а не обычными страницами (как раз страницы и требуются большинству разработчиков). HTM L-документы Зачастую разработчики практикуют внедрение кода JavaScript в HTML-документы. Однако внедрение сер- серверной части JavaScript в HTML-файл может существен- существенно изменить результат. Существуют два пути внедрения JavaScript в HTML-документы. ПерБый путь заключается в применении дескрипто- дескрипторов <server>n </server>. В любом случае, использова- использование этих дескрипторов напоминает дескрипторы <script> и </script>, применяемые на клиентской час- части JavaScript. Например, требуется сгенерировать стро- строку, которая отображает ID (идентификатор) лица, ра- ранее переданный через форму. Для этого можно прибегнуть к дескриптору <server>: Глава 12 <serveг> if (client, custid = null) { write("Вы не имеете идентификатора"); :) else { write ("Ваш идентификатор — " + client.custid); ) </server> Второй путь встраивания кода не предусматривает использование дескриптора <server>, поскольку код находится внутри другого HTML-дескриптора. Если не- необходимо поместить выражение JavaScript внутрь HTML-дескриптора, код окружается обратными кавыч- кавычками (\Q). Эти кавычки весьма полезны при работе с объектами Link, Anchor и Form. Например, генерирова- генерирование HTML-кода с созданной "на лету" ссылкой, кото- которая включает заранее введенный пользователем Web- адрес, достигается при помощи такого кода: <AHREF=\ ' client .WebAddress\ ' >Доиашыяя *¦ страница</А> При внедрении серверного JavaScript-кода в HTML- документ, пользователь видит только результат выпол- выполнения кода, но не сам код. Именно в этом и заключа- заключается различие между серверной и клиентской частями JavaScript, которое можно заметить только во время просмотра исходного файла в любом Web-браузере. Листинг 12.1 содержит исходный код HTML с вне- внедренным кодом JavaScript. Во время выполнения при- приложения (см. листинг 12.2) это именно то, что будет лицезреть клиент при просмотре исходного кода в Web- браузере. (Результат отображения показан на рис. 12.2.) Несколько позже в главе будет рассматриваться объект Client. Сейчас достаточно будет отнестись к выражени- выражениям как к свойствам недавно созданного и определенно- определенного объекта. Листинг 12.1. Внедренный серверный сценарий. <html> <head> <title>Feedback</title> </head> <body> "Superiffic" Feedback Confirmation Dear <server>client. firstName</server>, Thank you for submitting feedback about our product. If you have asked us to contact you, we will be using the following information: <blockquote> <strong> E-mail: <server>client.email</server> </strongXbr>
Базовое подмножество языка JavaScript Часть II <strong>Telephone: <server>client.phone </server> </strongXbr> <strong>FAX: <server>client.fax</server> </strong> </blockquote> <P> If any of this information is incorrect, please go back to the feedback form and ¦change it, We thank you for taking the time to help us be a "superiffic" company. Sincerely, Rupert Mydryl <br> Manager, Customer Services </body> </html> Листинг 12.2. Результирующий документ, передаваемый клиенту. <html> <head> <title>Feedback</title> </head> <body> "Superiffic" Feedback Confirmation Dear Charles : Thank you for submitting feedback about our product. If you have asked us to contact you, we will be using the following information: <blockquote> <strong> E-mail: chappy@smiles.com </strongXbr> •<strong> Telephone: 808-555-1212 </strongXbr> <strong> FAX: 808-555-5050 </strong> </blockquote> <P> If any of this information is incorrect, please go back to the feedback form and change it. We thank you for taking the time to help us be a "superiffic" company. Sincerely, Rupert Mydryl <br> Manager, Customer Services </body> </html> Ж ^ 'Superiffic" Feedback Pear Charles. "Piank you for flibmiteiefeftaback ab.-,ut out рто4и informaticn- E- m a il: Л ар py@imfl« i .r inn telephone: 308-555-1212 FAX: 808^55-5050 IFany ofЙи an'on ц incorrect, please go back to help щ Ъ« a "jupniffic" Company. M^nagrr, СиЛмйег Services '- .2 A l -.3 d^.:-\ Confirmation t IfTouhave askedus to contact ynu. wwin be i «if the Mowing о the feedback Form and change it We thank you for tskmelhc time РИСУНОК 12.2. HTML-документ в браузере. Библиотечные файлы JavaScript В любой серьезной среде разработки необходимо где-то размещать общие функции, которые можно вызывать из различных исходных файлов. Так же как и клиентская часть, серверная версия JavaScript позволяет размещать код JavaScript во внешних файлах, имеющих расшире- расширения .js. Внутри библиотечного файла JavaScript должны на- находиться функции, но не HTML. Ссылки на эти функ- функции можно производить внутри HTML-файла. После компиляции SSJS-приложения компьютер разрешает все вызовы внешних функций путем просмотра js-фай- лов, включенных в приложение. Подготовка приложения В отличии от клиентской части, процесс разработки серверной части требует компиляции исходных файлов в файлы приложений .web. По этой причине большин- большинство разработок SSJS — это Web-приложения. Далее поговорим о том, как создавать приложения и запускать их в Netscape Enterprise Server (NES). Активизация серверной части JavaScript Для того чтобы пользователи смогли получить доступ к приложению, потребуется активизировать серверную часть в экземпляре Enterprise Server. Для этого необхо- необходимо получить доступ к Enterprise Administration Server и выбрать серверный экземпляр, в котором и будет вы- выполняться активизация SSJS. Как только появится
Серверная часть JavaScript Server Manager для данного экземпляра, выберите вклад- вкладку Programs и щелкните на элементе меню Server Side JavaScript. Все что потребуется предпринять на этой странице (см. рис. 12.3) — так это выбрать соответству- соответствующий переключатель для активации SSJS и решить, требуется ли запрашивать пароль администратора при доступе к Server-Side JavaScript Application Manager (весьма неплохая идея). Не забудьте сохранить и при- применить произведенные изменения. После перезапуска экземпляра Enterprise Server, как того требует Administration Server, доступ к Application Manager (см. рис. 12.4) можно получить с использова- использованием показанного ниже URL. www.yourinstance.com необ- необходимо заменить на соответствующее имя сервера: http:/1www.yourinstance.com/appmgr Итак, среда Server-Side JavaScript уже запущена, можно подготовить и запустить свое приложение. РИСУНОК 12.3. Активизация Server-Side JavaScript в Netscape Enterprise Server 4. Web F Default Page: home htmt InirJalPage; start hinit Built-in UiudiniuiL DatmhateColraecriMU: 0 Mainieninre: г1кы cookit Sranu: _1 ¦: i..- им isd Глава 12 Компиляция приложений После создания исходных файлов для приложения, их необходимо откомпилировать. Компилятор, входящий в состав NES, создает из HTML-документа и библио- библиотечных файлов JavaScript файл .web, содержащий пос- последовательность байткодов. Для компиляции приложения потребуется перейти в командную строку и запустить программу компиля- компилятора JavaScript Application Compiler (jsac). B NES 4.01 этот исполняемый модуль расположен в подкаталоге bin\https\bin. Вот варианты запуска компилятора: jsac [-cdv] [-1 ходоваяТаблица] [-а версияЯзыка] -о двоичныНФайл [-i] исходныйФайл1 [-i] исходныйФайл2... jsac [-cdv] [-а версияЯзыка] -О двоичныйФайл -f файлВключения jsac [-cdv] [-а версияЯзыка] -О двоичныйФайл -р каталог ~/ файлВключения -г файлРетстрацииОшибок Рассмотрим допустимые опции, передаваемые в ко- командной строке: -а Версия языка JavaScript, например .2". -с Выполнять только проверку синтаксиса без гене- генерации файла двоичныйФайл. -d Активизировать режим отладки. -f Включение файла, заданного именем файлВклю- файлВключения. -h Вывести справочную информацию по опциям ко- командной строки компилятора. -i Определить имя исходного файла (исходный- файл). -1 Имя набора символов (например, iso-8859-1или x-sjis). -о Определить имя создаваемого файла .web как дво- двоичныйФайл. -р Текущий путь при обработке файлов. -г Перенаправить вывод сообщений об ошибках в указанный файл (файлРегистрацииОшибок). -V Компилировать с расширенными сообщениями. Например, следующее командная строка компили- компилирует (с расширенным выводом) приложение SSJS в файл policy.web, используя три исходных HTML-фай- HTML-файла (index.htm, toc.htm, polpage.htm) и два библиотечных файла JavaScript (jsroutines.js и jsdates.js): jsac -v -о policy.web index.htm toc.htm polpage.htm jsroutines.js jsdates.js СОВЕТ РИСУНОК 12.4. Менеджер приложений Server-Side JavaScript. После активизации Server-Side JavaScript на Web-серве- Web-сервере, можно осуществлятьудаленную компиляцию прило- приложений, выполнив доступ к программе jsacRemofe, посту-
Базовое подмножество языка JavaScript Часть II пающей вместе с Application Manager. Просто введите URL в свой экземпляр Enterprise Server и воспользуйтесь /jsacremote в качестве пути для доступа к приложению. Инсталляция приложений Для инсталляции приложения на сервере с использова- использованием Server-Side JavaScript Application Manager, щелк- щелкните на вкладке Add Application. После выбора этой вкладки в правом фрейме окна отобразится HTML-фор- HTML-форма, которую потребуется заполнить (см. рис. 12.5). РИСУНОК Xl Добавление приложения. Заполните форму, основываясь на следующей ин- информации: ¦• Name (Имя). Введите имя приложения. Оно необхо- необходимо для доступа к приложению после его инстал- инсталляции. Например, если имя приложения — fireball, a URL сервера — www.junebug.com, доступ к нему можно получить так: http://www.junebug.com/fireball ПРЦДУПРЕЖДЕНИЕ Убедитесь, что приложению не присваивается имя, со- совпадающее с именем существующего каталога на сер- сервере. Если совпадение имеет место, клиент не сможет получить доступ к этому каталогу сервера. • Web File Path (Путь к .web-файлу). Введите полный путь и имя файла Web-приложения. • Default Page (Страница по умолчанию). Введите имя HTML-файла, который будет служить страницей по умолчанию для приложения. Страница по умолча- умолчанию отображается, когда клиент, получивший дос- доступ к приложению, не определяет файл в запросе. • Initial Page (Начальная страница). Введите имя HTML-файла, который будет служить начальной страницей, когда клиент получает доступ к прило- приложению. Эта информация необязательна. • Built-in Maximum Database Connections (Максималь- (Максимальное число встроенных соединений баз данных). Вве- Введите максимальное количество одновременных со- соединений, которые допускаются сервером баз данных, выполняющимся под управлением операци- операционной системы NY Server. • External Libraries (Внешние библиотеки). Если при- приложение использует внешние библиотеки (например, библиотеки динамической компоновки, или DLL), введите здесь полный путь доступа к ним. • Client Object Maintenance (Поддержка объекта Client). Это поле определяет режим поддержки по- постоянства объекта Client. Допустимые 1арианты включают: client-cookie, client-url, server-ip, server- cookie и server-url. По заполнении информации о приложс ши, щелк- щелкните на кнопке ОК в нижней части страницы. Application Manager проверит введенные значения на предмет наличия ошибок и затем выполнит инсталля- инсталляцию приложения на сервере. После инсталляции потребуется вернуться на вклад- вкладку Applications и убедиться, что ваше приложение в списке присутствует. Запустите приложение, щелкнув на Run. Доступ к приложению производится путем вво- ввода адреса URL, где находится Enterprise Server, и сле- следующего за этим URL имени приложения, отделенно- отделенного наклон чертой вправо. Рассмотрим пример вызова приложения туАрр: http ://www.mysi te.com/туApp ПРИМЕЧАНИЕ После внесения определенных изменений в входные тексты приложения и его повторной компиляции, при помощи Application Manager перезапустите приложение, чтобы изменения возымели действие. . ,.. ., „., ... Исправление ошибок Теперь, когда запуск произведен, следует получить до- доступ к приложению, дабы убедиться, что все работает предсказуемым образом. Если это действительно так, можно разрешать доступ к приложению и другим пользователям. Если же возникают какие-то проблемы, потребуется запустить отладчик приложений и выяс- выяснить, в чем же дело. Общая отладка При работе с клиентской и серверной частями JavaScript, можно прийти в некоторое замешательство, поскольку
Серверная часть JavaScript ¦НУ по идее отлаживать необходимо как серверную, так j4 клиентскую часть. Внутри Application Manager суще- существует отладчик, доступ к которому можно получить путем выбора приложения из списка и щелчка на кноп- кнопке Debug. В результате открывается новое окно браузе- браузера с фреймом (или окном) трассировки, как показано на рис. 12.6. Окно трассировки отображает текущие объекты и их свойства. Также можно прибегнуть к ус- услугам встроенной функции debug(), действующей по- подобно функции write(), для вывода в окно трассировки результатов вычисления JavaScript-выражения. ; ¦ F.,m..h|-J Ф-42? 0 0 1- Ш T-jitiel jiniJHrt ub|t.l 1 bdul inrver tbject Я hqit="faL«aLtL'L ^j : ; = ¦ ¦¦¦¦¦¦¦¦¦¦ ¦ 1 & щ РИСУНОК 12.6. Отладчик Server-Side JavaScript Application Manager. Ошибки, связанные с базами данных Большинство методов, используемых для взаимодей- взаимодействия с базами данных, возвращают код состояния. Код состояния представляет собой целое число от 0 до 27. Код 0 уведомляет о ТОМ, что команда выполнена успеш- успешно, в то время как другие значения, перечисленные в табл. 12.1, указывают на ошибки, возникающие на сер- сервере. Объект базы данных имеет четыре отладочных ме- метода, которые возвращают код ошибки и соответствую- соответствующее сообщение от сервера баз данных. Значения того, Глава 12 что возвращается, зависит от сервера баз данных. В табл. 12.2—12.5 перечислены возвращаемые значения для че- четырех поддерживаемых SSJS баз данных SQL. Таблица 1 I. Коды состояния баз данных. Код Описание состояния О 1 2 3 4 5 6 7 8 9 10 И 12 13 14 15 16 17 я 19 20 21 22 23 24 25 26 27 Ошибок нет. Недостаточно памяти. Объект не инициализирован. Ошибка преобразования типов. Незарегистрированная база данных. Ошибка, выданная сервером. Сообщение отсервера. Ошибка от библиотеки поставщика. Потеря связи. Операция считывания завершена. Неправильное использование объекта. Столбец не существует. Неправильное размещение внутри объекта (ошибка выхода за границы). Неподдерживаемая возможность. Нулевая ссылка. Объект базы данных не найден. Отсутствует необходимая информация. Объект не поддерживает множественное чтение. Объект не поддерживает удаление. Объект не поддерживает вставку. Объект не поддерживает обновление. Объект не поддерживает обновление. Объект не может поддерживать индексы. Объект не может быть удален. Неправильное подключение. Объектнеподдерживаетпривилегии. Объект не поддерживает курсоры. Открытие невозможно. Таблица 12.2. Библиотека ошибок производителя Informix (код состояния 7). Метод Что возвращает majorErrorMessageO minorErrorMessage() imajorErrorCode() minorErrorCodeO Vendor Library Error: errorMsg (Ошибка библиотеки производителя: errorMsg) {errorMsg — это текст от Informix). ISAM Error: errorMsg (Ошибка ISAM: errorMsg) {errorMsg— текст кода ошибки ISAM от Informix либо пустая строка (""), если ошибки ISAM нет). Кодошибки Informix. Код ошибки ISAM либо нуль, если ошибки нет.
Базовое подмножество языка JavaScript Часть II Таблица 12.3. Ошибки сервера Oracle (код состояния 5). Метод Что возвращает majorErrorMessage() minorErrorMessageO imajorErrorCode() iminorErrorCode() Server Error: errorMsg (Ошибка сервера: errorMsg) (errorMsg — трансляция кода возврата Oracle). Имя сервера Oracle. Возвращает код, переданный Oracle Call-level Interface (OCI). Код ошибки операционной системы, переданный OCI. Таблица 12.4. Библиотека ошибок производителя Sybase (код состояния 7). Метод' Что возвращает majorErrorMessage() minorErrorMessageO imajorErrorCodeQ minorErrorCode() Vendor Library Error: errorMsg (Ошибка библиотеки производителя: errorMsg) (errorMsg—это текстошибки, полученный от DB-Library). Текст ошибки операционной системы (в соответствие со спецификацией библиотеки DB- Library). Номер ошибки DB-Library. Степень серьезности ошибки (в соответствие со спецификацией библиотеки DB-Library). Таблица 12.5. Ошибки сервера Sybase (код состояния 5). Метод Что возвращает majorErrorMessage() minorErrorMessage() majorErrorCodeO minorErrorCodeO Server Error: errorMsg (Ошибка сервера: errorMsg) (errorMsg — текст, возращенный сервером SQL). Если степень серьезности ошибки и номер сообщения равны 0, возвращается только текст сообщения. Имя сервера SQL. Номер сообщения сервера SQL. Уровень серьезности (в соответствие со спецификацией сервера SQL). Базовые серверные объекты JavaScript Теперь, когда имеется представление о работе модели клиент/сервер в пространстве Internet и особенностях функционирования серверной части JavaScript, можно перейти к рассмотрению объектов, доступных при по- построении приложений (рис. 12.7). Основная цель сер- серверных объектов заключается в управлении постоянны- постоянными данными. Внутри Web-среды, не поддерживающей концепцию состояний, эти объекты могут постоянно хранить различные типы данных для разных запросов одного и того же клиента, для запросов множества кли- клиентов и даже для различных приложениях SSJS. Объект Server Объект Server используется для управления глобальны- глобальными данными о самом сервере. Этот объект всегда при- присутствует на сервере SSJS и создается при его запуске. Он разрушается при завершении сервера. Встроенные методы и свойства объекта Server перечислены в табл. 12.6. РИСУНОК 12.7. Структура базовых серверных объектов JavaScript.
Серверная часть JavaScript Глава 12 Таблица 12.6. Встроенные методы и свойства объекта Server. Тип Элемент Метод Свойство lock() unlockO host ihostname jsVersion iport protocol Описание Блокирует код во время выполнения манипуляций сданными с одним потоком. Освобождение ранее заблокированного кода. Строка, определяющая имясервера, субдомена и домена\Л/еЬ-сервера. Полное имя сервера (включая порт); то же самое, что и объединение свойств host и port. Серверная версия JavaScript и платформа. Номер порта используемого сервером. Используемый Internet-протокол, присутствующий в адресе Ш1_до первого двоеточия. Для того чтобы глубже понять работу методов lock() и unlock(), изучите следующий раздел, посвященный объекту Project. Методы этого объекта действуют совер- совершенно аналогично. Объект Project Объект Project разработан с целью поддержки инфор- информации о приложениях на клиентской части и обеспе- обеспечения постоянства до тех пор, пока приложение на сер- сервере не будет закрыто. Данный объект не содержит свойств, но только два метода, описанные в табл. 12.7. Таблица 12.7. Встроенные методы объекта Project. Метод Описание lock() Блокирует код во время выполнения манипуляций сданными, к которым подключен только один поток. unlock() Освобождает ранее заблокированный код. Благодаря многопользовательской природе Web, к приложению SSJS могут одновременно получить дос- доступ сотни и тысячи пользователей. В результате, впол- вполне вероятна ситуация, когда большое число пользова- пользователей одновременно пытаются выполнить чтение или запись в объект Project. SSJS обеспечивает скрытое бло- блокирование на весь период чтения и записи значения свойства. Начиная с Netscape Enterprise Server 4.01, для объек- объектов Project и Server скрытое блокирование не реализу- реализуется, как это имело место в предыдущих версиях. Иногда требуется явная блокировка. Примером мо- может послужить установка начального значения для уве- увеличивающегося номера, скажем, накладной, которое хранится в свойстве. Для это необходимо прочитать старое значение, прибавить к нему какую-то величину и присвоить новое значение свойству. Скрытая блокировка в данном случае не срабатыва- срабатывает, однако, для достижения требуемой цели можно при- прибегнуть к услугам метода lock() объекта Project. Метод lock() обеспечивает явную блокировку объекта вплоть до вызова метода unlock(). Например, для установки нового номера накладной можно использовать такой код: proj ect.lock() ; project.invoiceNum += 1; project.unlock(); Если в этот момент доступ к объекту Project пыта- пытается получить другой клиент, ему придется ожидать завершения текущего процесса. ; примечание ';:,„;г-"** ! , SSJS гарантирует отсутствие внутри экземпляра Project взаимной блокировки (или коллизии), когда два объекта блокируют базу данных. Это достигается автоматичес- автоматическим освобождением всех блокировок после отработки клиентского запроса. Объект Client Как было показано, объекты Request существуют толь- только в определенные моменты времени. Поскольку взаи- взаимодействие клиента с серверным приложением предпо- предполагает наличие более одного запроса, для поддержки состояния в течение серии запросов используется объект Client. Новые экземпляры объекта Client созда- создаются каждый раз, когда новый клиент получает доступ к приложению. Подобно Project, объект Client не име- имеет свойств, но лишь только два метода, краткое описа- описание которых приводится в табл. 12.8. Таблица 12.8. Встроенные методы объекта Client. Метод Описание destroy() Метод явно разрушает объект и все свойства, поддерживаемые объектом. expiration() Метод позволяет изменять 10-минутное по умолчанию истечение времени действия объектов Client на другой промежуток времени.
Базовое подмножество языка JavaScript Часть II Объект Client разработан таким образом, чтобы са- саморазрушаться по прошествии определенного проме- промежутка времени. Основная причина заключается в том, что требуется поддерживать состояние в клиентских запросах, однако совершенно невозможно определить, какой запрос является последним. Поскольку никто не желает оставлять в памяти множество неиспользованных объектов Client, необходимо автоматически разрушать объект по истечению определенного промежутка време- времени. Время жизни объекта по умолчанию — 10 минут. Это значение можно изменить при помощи метода expiration(). Например, для увеличения периода времени до 20 минут потребуется записать следующий код: client.expirationA200); Для изменения упомянутого времени метод expiration() должен вызываться на каждой странице приложения. Страницы, не имеющие обращения к expiration(), будут использовать значение времени по умолчанию. Объект Request Листинг 12.3. Регистрационнаяформа. <html> <head> <title>PeriicTpaitfta</title> </head> <body> <hl>Registration</hl>¦ <hr> <form action="/ssjs/objects" method="POST"> Please provide the following contact information: Экземпляр этого объекта создается каждый раз, когда сервер получает новый запрос. Объект Request содержит данные текущего запроса клиента. Он обладает множе- множеством свойств, перечисленных в табл. 12.9. Как упоминалось в табл. 12.9, объект Request также имеет определенные свойства для каждого элемента ввода переданной HTML-формы — formkey. Например, пользователь передает форму, описание которой приво- приводится в листинге 12.3. Когда на основе отправленной формы создается объект Request, с ним ассоциируются следующие свойства: request.FullName request.Title request.Organization request.Email Таблица 12.9. Встроенные свойства объекта Request. <em>Name</em> <input type="text" size=5" maxlength=5 6" name="FullName "Xbr> <em>Title</em> <input type="text" size=5" maxlength=56" name="Title"Xbr> <emX3rganization</em> <inpilt type="text" size=S" maxlength=56" name="Organization" Xbr> <em>E-mail</em> <inpilt type="text" size=5" maxlength=56" name="Email"Xbr> <p> <inpilt type="submit" value="Submit"> i type=lireset" value="Reset"> </form> </body> </html> Единственный элемент формы, который обрабаты- обрабатывается специальным образом, — это объект Select с возможностью выбора множества значений (в <select> параметр multiple находится в установленном состо- состоянии). В данной ситуации имеет смысл воспользова- воспользоваться встроенными функциями getOptionValue() и getOptionVa!ueCount(), организовав проход по множе- множеству выбранных значений объекта Select. Функция getOptionValue() определяется следующим образом: getOptionValue (name, index) : Свойство Описание agent auth_type authuser formKey imageX imageY ip method protocol query Информация о клиентском программном обеспечении (т.е. название и версия). Тип авторизации; соответствует переменной AUTH_TYPE среды CGI. Имя локального HTTP-пользователя браузера, если активизирована авторизация доступа HTTP. Соответствует переменной REMOTEJJSER среды CGI. Представляет любой ключ формы, отправленный браузером. Горизонтальная координата курсора мыши над картой изображения. Вертикальная координата курсора мыши над картой изображения. .IP-адрес клиента. Метод HTTP (обычно GET или POST). Уровень HTTP-протокола клиента. Содержит информацию, передаваемую в URL после знака ?. Соответствует переменной QUERY_STRING среды CGI.
Серверная часть JavaScript Параметр пате — это имя объекта Select, а параметр index — индекс массива вариантов. Обратите внимание на список вариантов в объекте Select, определенных в листинге 12.4 и показанных на рис. 12.8. После пере- передачи формы на сервер, запрашивается код из листинга 12.5. При помощи знакомого цикла for можно пройтись по всем выбранным элементам. На рис. 12.9 показана результирующая HTML-форма, динамически сгенери- сгенерированная обращениями к write(). Листинг 12.4. Форма для отбора песен. <html> <head> < title> Song- Picker < /title> </head> <body> <h2>Pick Your Favorite Songs From the List: </h2> <form action="topsongs.htm" method="post" name="songSelect"> <select name="songs" size=0" multiple> <option>1979 (Smashing Pumpkins) </option> <option>Breakfast at Tiffany's (Deep "-•Blue Something) </option> <option>Don't Cry (Seal)</option> <option>Flood (Jars of Clay) </option> </select> <input type="submit" value="Submit"> </form> </body> </html> Pick Your Favorite Songs From the List: 1979 (Smashing Pumpkins) 3reakfa-;l at Tiffany's (Deep Blue Something) lonl Cry (Seal) Float) (Jars of Clay) ¦ ¦ ¦ РИСУНОК 12.8. Список с возможностью множественного выбора перед передачей формы. Листинг 12.5. Код со стороны сервера для обработки списка выбранных песен. <html> <head> <title>Results Page</title> </head> <body> Глава 12 <server> write ("<h2>The songs selected included:</h2>") , write("<ul>"); var size = getOptionValueCount("songs"); for (var i = O; i < size; i++) { write("<li>" + getOptionValue("songs" , i) write("</ul>"); </server> </body> </html> it * if The songs selected included: • Breakfast at Tiffany's (Deep Blue Something) ¦• Flood (Jais ofCIay) РИСУНОК 12.9.Динамически сгенерированный документ. Объект Lock Данный объект используется для обеспечения блокиро- блокировок других объектов. Как упоминалось ранее, этот про- процесс обеспечивает защиту доступа к данным со стороны определенных экземпляров в случае, когда предполага- предполагается только единственный поток операций. Наглядный пример тому — счетчик. К е 111 услугам прибегают, ска- скажем, тогда, когда необходимо посчитать количество клиентов или запросов, пришедших за фиксированный промежуток времени. У объекта есть три метода и един- единственное свойство, перечисленные в табл. 12.10. Объект File Вплоть до сего момента рассматривались только своего рода "автоматические" объекты. Под "автоматическими" объектами подразумеваются только такие, к созданию которых в среде SSJS приводит запуск самого сервера, получение запросов, поддержка проектов и of блокировок. Первый объект, выходящий за пределы очерченной области, — это объект File.
Базовое подмножество языке JavaScript Часть II Объект File позволяет считывать и записывать дан- данные в файл, хранящийся в файловой системе сервера. Команды для чтения и записи в файл относятся к стан- стандартным функциям большинства языков программиро- программирования. Если доводилось использовать другие языки про- программирования, особых неудобств испытывать не придется. Данный объект имеет всего одно свойство и несколько методов, краткое описание которых приво- приводится в табл. 12.11. Новые экземпляры объекта File создаются при помо- помощи оператора new. Рассмотрим один пример: var fileObject = new File("path"); Поскольку объект File имеет дело с файловой сис- системой сервера, параметр path должен содержать полный путь к файлу, но не URL. После создания экземпляра объекта, его потребуется открыть для подготовки либо к считыванию, либо к записи, вызвав метод ореп(). В этот метод передается параметр mode, который может принимать одно из значений, перечисленных в табл. 12.12. Возможно, вы обратили внимание на необязатель- необязательный параметр Ъ, используемый для открытия файлов в двоичном режиме только в среде операционной системы Windows. После завершения работы с открытым файлом потребуется вызвать метод close() для его закрытия. Icobet" . >.", *^v\ "'¦¦¦' d" ' "• " .- Несмотря на то что объект File не имеет методов lock|) и unlock!), возможности блокировки оказываются дос- доступными через объекты Project и Server. Листинг 12.6 демонстрирует один из способов ис- использования файлов. Приведенный код предназначен для регистрации пользователей, передавших форму. При каждой передаче формы серверный сценарий открыва- открывает файл contlog.txt и записывает в него содержимое всех полей, используя запятые в качестве разделителей. Таблица 12.10. Встроенные методы и свойства объекта Lock. Тип Метод Описание Метод Свойство isValidO ilock() unlockO prototype Проверяет допустимость конструкции объекта Lock. Блокирует код на период выполнения манипуляций с данными, которые должны осуществляться в эксклюзивном режиме. Освобождает ранее заблокированный код. Позволяет добавлять новые методы и свойства в объект Lock. Таблица 12.11. Свойства и методы объекта File. Тип Элемент Описание Преобразует число, представленное в одном байте, в строку. Очищает состояние ошибки для файла. Закрывает файл. Определяет, находится ли указатель в конце файла. Возвращает текущее состояние ошибки. Определяет, существует ли определенный файл. Записывает в файл содержимое внутреннего буфера. Вьиает длину файла. Выдает текущую позицию указателя в файле. Открывает файл для доступа. Считывает данные из файла в строку. Считывает заданное количество байтов и возвращает их значение. Считывает текущую строку файла в строковую переменную. Устанавливает текущую позицию в файле. Преобразует первый число, находящееся в строке, в значение, представленное байтом. Записывает данные в файл. Записывает один байт данных в файл. Записывает данные в файл с добавлением кода возврата каретки. Позволяет добавлять методы и свойства в объект File. Метод Свойство byteToStringO clearError() close() eof() error() exists() flush() getLength() getPositionQ open() read() readByte() readln() setPosition() stringToByte() write () writeByte() writelnf) prototype
Таблица Mode 12. 12. Параметры Описание метода ореп() для объекта File. Серверная часть JavaScript шрм Глава 12 ЦЦ а[Ь] Открывает существующий файл для добавления нового текста. Если файл не существует, он создается. а+[Ь] Открывает существующий файл для чтения и записи. Если файл не существует, возвращается false. Указатель устанавливается в конец файла. r[b] Открывает существующий файл для чтения. Если файл не существует, возвращается false. r+[b] Открывает существующий файл для чтения и записи. Если файл не существует, возвращается false. Указатель устанавливается в начало файла. w[b] Открывает новый файл для записи. Если файл уже существует, происходит его перезапись. w+[b] Открывает новый файл для чтения и записи. Если файл уже существует, происходит его перезапись. Листинг 12.6. Работа с файлами через объект File. <html> <head> < ti Ъ1е>Регистрация< / ti tle> </head> <body> <server> if (request. FullName != null) ( cLog = new File ("d:/netscape/suitespot/server4/logs/contlog.txt") ; project.lock(У ; if (cLog.open("a") = true) { cLog.write (request. FullName + ","); cLog. write (request.Title + ","); cLog. write (request.Organization + ","); cLog.write (request.Email + ","); cLog.close(); project.unlock (); ) </server> <hl>Registration</hl> <hr> <form aetion="/ssjs/objects" method="POST"> <P> Please provide the following contact information: <em>Name</em> <input type=text size=35 maxlength=256 name="FullName"Xbr> <em>Ti tle</em> <input type=text size=35 maxlength=256 name="Title"Xbr> <em>Organiz ati on< / em> <input type=text size=35 maxlength=256 name="Organization"Xbr> <em>E-mail</em> <input type=text size=25 maxlength=2S6 name="Email"Xbr> <P> <input type=submit value="Submit"> <input type=reset value="Reset"> </form> </body> </html> ОбъеКТ SendMail бы пользователям возможности по отправке почтовых сообщений. Методы и свойства SendMail перечислены Еще один весьма полезный объект SendMail позволяет в табл. 12.13. отправлять сообщения через почтовый сервер. Как и Подобно объекту File, SendMail создается с исполъ- Предг! слагалось, при помощи этого объекта можно со- зованием оператора new: ЗДавать страницы приложения, которые предоставляли . .. r r r r var myMessage = new SendMail () ;
Базовое подмножество языка JavaScript Часть II Таблица 12.13. Методы и свойства объекта SendMail. Тип Элемент' Описание Метод errorCodeQ Возвращает целочисленное представление кода ошибки, возникшей во время отправки сообщения. errorMessage() Возвращает строку, связанную с кодом ошибки, возникшей во время отправки сообщения. send{) Отправляет электронную почту. Свойство Вес Разделенный запятыми список адресатов, получаемых скрытую точную копию сообщения. Body Основной текст сообщения. Сс Разделенный запятыми список адресатов, явно получаемых точную копию сообщения. Errorsto Имя пользователя, которому будут адресоваться сообщения об ошибках при отгравке. Значение по умолчанию совпадает со значением свойства From. From Обязательное имя отправителя сообщения, ¦Organization Название компании-отправителя или любая информация о ней. prototype Позволяет создавать новые свойства и методы для объекта SendMail. Replyto Имя пользователя, используемое вместо свойства From в качестве адреса, куда будет отправляться ответное сообщение. Smtpserver Имя хоста или IP-адрес SMTP. Subject Предмет сообщения. То Список получателей сообщения, разделенный запятыми Объекты баз данных Одно из преимуществ серверной части JavaScript заклю- заключается в возможности взаимодействия с базами данных. Как упоминалось ранее, LiveWire вызывает SSJS, для чего, собственно, последний и используется. В настоя- настоящий момент LiveWire относится к функциональным средствам доступа к базам данных в среде SSJS. Чуть ниже будут рассматриваться базовые объекты, обеспе- обеспечивающие упомянутый доступ. Объект Database Объект Database инкапсулирует всю функциональность взаимодействия с реляционными базами данных. У дан- данного объекта определено всего лишь одно свойство, в то' Таблица 12.14. Методы и свойства объекта Database. время как большинство действий реализуется через ме- методы. Таблица 12.14 содержит краткие описания всех методов. Если до этого приходилось работать с базами данных в других языках программирования, несложно заметить, что JavaScript обладает практически всеми средствами взаимодействия с базами данных. Объект DbPool Объект DbPool, появившийся в Netscape Enterprise Server 3, очень напоминает объект Database с тем лишь отличием, что этот объект представляет целиком весь пул подключений к базе данных. После создания тако- такого пула, из него можно вытаскивать необходимые со- соединения. В табл. 12.15 представлены методы и свой- свойство данного объекта. Тип Элемент Описание Метод beginTransaction() commitTransactionO connect() connected() ¦cursorQ. disconnect) executeO majorErrorCodeO Начинает транзакцию SQL. Выполняет текущую транзакцию SQL. Подключает приложение кзаданной базе данных. Возвращает true, если связь между приложением и базой данных установлена. Создает объект Cursor для заданной SQL-оператора SELECT, Разрывает связь с базой данных. Выполняет заданный оператор SQL. Используется для операторов SQL, которые не возвращают курсор. Главный код ошибки, возвращаемый сервером баз данных или ODBC.
Серверная часть JavaScript Тип Глава 12 Элемент Описание Свойство majorErrorMessage() minorErrorCode() iminorErrorMessage() rollbackTransaction() SQLTableO stored Proc() stored ProcArgs() toStringf) prototype Сообщение, соответствующее главному коду ошибки, возвращаемое сервером баз данных или ODBC. Вторичный код ошибки, возвращаемый библиотекой поставщика. Сообщение, соответствующее вторичному коду ошибки, возвращаемое библиотекой поставщика. Выполняет откат текущей транзакции SQL. Генерирует HTML-таблицу для вывода на экран результатов запроса SELECT. Создает объект Stproc и запускает выбранную хранимую процедуру. Создает прототип хранимой процедуры DB2, ODBC или Sybase. Возвращает строку, представляющую заданный объект. Позволяет добавлять методы и свойства к экземплярам объектов Database. Таблица 12.15. Методы и свойства объекта DbPool. Тип Элемент Описание Метод Свойстзо connectf) connectedQ connection () DbPoolO disconnect) imajorErrorCode() majorErrorMessage() iminorErrorCodeO minorErrorMessage() storedProcArgsQ toString() prototype Подключает пул приложения к заданной базе данных. Возвращает true, если пул подключен к базе данных. Захватывает доступное соединение из пула. Создает пул соединений с базами данных. Закрывает все соединения с базами данных в пуле. Главный код ошибки, возвращаемый сервером баз данных или ODBC. Сообщение, соответствующее главному коду ошибки, возвращаемое сервером баз данных или ODBC. Вторичный код ошибки, возвращаемый библиотекой поставщика. Сообщение, соответствующее вторичному коду ошибки, возвращаемое библиотекой поставщика. Создает прототип хранимой процедуры DB2, ODBC или Sybase. Возвращает строку, представляющую заданный объект. Позволяет добавлять методы и свойства к экземплярам объектов DbPool. Объект Connection Объект Connection появился в Netscape Enterprise Server .3 и представляет собой связь, взятую из резерва связей с базами данных. Создается этот объект с помощью вызова метода DbPool.connection (). В таблице 12.16 представлены методы и свойство данного объекта. Объект Cursor Данный объект создается за счет вызова методов Connection.cursor() или database.cursor(). Поскольку запрос к базе данных требует вернуть курсор, этот объект содержит ссылку на строки, возвращаемые в ре- результате выполнения запроса. В таблицу 12.17 сведены методы и свойства этого объекта. Таблица 12.16. Методы и свойство объекта Connection. Тип Элемент Описание Метод beginTransactionQ eommitTransactionO connectedQ cursor() execute() imajorErrorCodeO Начинает транзакцию SQL. Выполняет текущую транзакцию SQL. Возвращает true, если связь между приложением и базой данных установлена. Создает объект Cursor для заданной SQL-оператора SELECT. Выполняет заданный оператор SQL. Используется для операторов SQL, которые не возвращают курсор. Главный код ошибки, возвращаемый сервером баз данных или ODBC.
Базовое подмножество языка JavaScript Тип Часть II Элемент Описание Свойство majorErrorMessage() iminorErrorCode() minorErrorMessageO release {) rollbackTransaction() SQLTableO storedProc() toStringO prototype Сообщение, соответствующее главному коду ошибки, возвращаемое сервером баз данных или ODBC. Вторичный код ошибки, возвращаемый библиотекой поставщика. Сообщение, соответствующее вторичному коду ошибки, возвращаемое библиотекой поставщика. Освобождает соединение, возвращая его в пул. Выполняет откат текущей транзакции SQL. Генерирует HTML-таблицу для вывода на экран результатов запроса SELECT. Создает объект Stproc и запускает выбранную хранимую процедуру. Возвращает строку, представляющую заданный объект. Позволяет добавлять методы и свойства к экземплярам объектов Database. Таблица 12.17. Методы и свойства объекта Cursor. Тип Элемент Описание Метод close() Закрывает курсор и освобождает занимаемую им память. columnNameO Принимает проиндексированную позицию столбца и возвращает соответствующее имя столбца. columns() Возвращает количество столбцов в рамках курсора. deleteRowQ' Удаляет текущую строкутаблицы. insertRow() Вставляет новую строку в таблицу. next() Перемещает экземпляр объекта Cursor из текущей строки на следующую. lupdateRowO Обновляет текущую строкууказанной таблицы. Свойство columnName Представляет имена столбцов, возвращаемых курсором. prototype Позволяет добавлять методы и свойства к экземплярам объекта Cursor. Объект Resultset Данный объект (результирующий набор) создается пос- после вызова метода Stproc.resultSet(). В нем сохраняются результаты выполнения хранимой процедуры. В случае выполнения процедур в базах данных DB2, Oracle, Sybase и ODBC объект Resultset возвращается для каж- каждого оператора SELECT. В сервере Infomix будет воз- возвращаться только один объект Resultset. В табл. 12.18 перечислены методы и свойства данного объекта. Объект Stproc Объект Stproc создается в результате вызова методов Connection.storedProc() или database.storedProc() и вы- Таблица 12.18. Методы и свойство объекта Resultset. полняет хранимую процедуру в базе данных, к которой получен доступ. Убедитесь, что вызов метода close() производится по завершении выполнения процедуры. В табл. 12.19 перечислены методы и свойства объекта. Объект BLOB Последний базовый объект, достойный рассмотрения, обеспечивает поддержку работы с Binary Large Objects (большие двоичные объекты, BLOB) в базе данных. Объект не обладает свойствами, лишь только двумя методами (см. табл. 12.20). Тип Элемент Описание Закрывает результирующий набор и освобождает занимаемую им память. Принимает проиндексированную позицию столбца и возвращает соответствующее имя столбца. Возвращает количество столбцов в результирующем наборе. Перемещает экземпляр объекта Resultset из текущей строки на следующую. Позволяет добавлять методы и свойства к экземплярам объекта Resultset. Метод Свойство close;) columnName() columnsQ next() prototype
Таблица Тип 12.19. Методы Элемент и свойства объекта Stproc. Описание Серверная часть javascript WWTfM Глава 12 ЕШ Метод closeQ Закрывает экземпляр хранимой процедуры, освобождая занимаемую им память. outParamCountQ Возвращает количество выходных параметров процедуры. outParameters() Возвращает значение определенного выходного параметра. resu!tSet() Создает новый объект Resultset. returnValue() Ввдает значение возврата хранимой процедуры. Свойство prototype Позволяет добавлять методы и свойства к экземплярам объекта Stproc. Таблица 12.20. Методы объекта BLOB. Метод Описание ЫоЫтадеО Извлекает из базы данных и отображает экземпляр данных типа BLOB. blobLinkQ Извлекает из базы данных и отображает HTML-ссылку, которая адресуется на экземпляр данных типа BLOB. Резюме Перед тем как приступить к созданию Internet-прило- Internet-приложений, следует разобраться в их архитектуре. Предва- Предварительный доступ к серверу окажет существенную по- помощь в выборе метода разработки приложений типа клиент/сервер. Функциональность JavaScript вместе с механизмом баз данных позволяет перевести приложе- приложения на новый качественный уровень. Отдавая предпочтение клиентской или серверной обработке, следует принять во внимание быстродействие и функциональность приложений JavaScript. He забы- забывайте, что двух- и л-уровневая модели обладают как достоинствами, так и недостатками, и присущими им степенью сложности и сопровождения. Данная глава продемонстрировала, что в JavaScript важна не только клиентская, но и серверная часть. С использованием Netscape Server-Side JavaScript этот' язык сценариев можно применить даже для создания целых Web-приложений.
Использование DOM ЧАСТЬ В ЭТОЙ ЧАСТИ 13. Основы объектной модели документец (DOM) 14. Управление событиями! 15. Объект Window 16. Объект Document 17. Объекты Form 18. Объекты Frame 19. Другие DOM-объекты
Основы объектной модели документа (DOM) В ЭТОЙ ГЛАВЕ Понятие объектной модели документа Навигация по таблице Управление документами Навигация по документу В этой главе приводятся начальные понятия, каса- касающиеся объектной модели документа (Document Object Model — DOM) и ее назначения, характеристик, объек- объектов и некоторых важных методов и свойств. Конечно, здесь рассматриваются только основные принципы, например, навигация по документам, а также их визу- визуализация в виде деревьев DOM. В данной главе будут показаны важные методы DOM, которые работают не- непосредственно с деревьями, хотя более детальные по- пояснения будут даны в главе 19, где DOM-модель рассмат- рассматривается с точки зрения JavaScript. Понятие объектной модели документа Ключевые успехи Web помогают решить давно стоящие проблемы. Например, Java обеспечивает путь разработ- разработки независимых от платформы прикладных Web-прило- Web-приложений с помощью аплетов, тогда как DOM-модель по- постепенно решает другую довольно старую (хотя и не столь важную) проблему создания JavaScript-сценариев и программ на Java, переносимых в контексте Web-бра- Web-браузеров. Это достигается за счет использования стандар- стандартных прикладныхпрограммныхинтерфейсов (application programming interfaces — API), которые входят в язык определения интерфейсов (Interface Definition Language — IDL), созданный Рруппой управления объектами (Object Management Group — OMG), и поэтому могут использоваться любым IDL-совместимым языком. Кол- Коллективный DOM API можно считать методом стандар- стандартизации объектов в браузерах при распространении HTML- и XML-документов. Web-браузеры становятся DOM-совместимыми, причем этот процесс идет быстры- быстрыми темпами. О DOM-модели, фактически, можно сказать немно- немногое. Она просто определяет логическую и стандартизи- стандартизированную структуру документа. Это дает возможность формировать, редактировать и просматривать элементы и содержимое в HTML- или XML-документах. Струк- Структура DOM — это всего лишь объектная иерархия, сопо- сопоставимая с иерархией в JavaScript или любом другом основанном на объектах языке. Различие в том, что DOM-модель имеет полезный API, который является нейтральным языком и определяет стандартный набор интерфейсов. Это не означает, что все прикладные про- программы DOM будут основаны на одних и тех же объек- объектах; они должны определять собственные интерфейсы и объекты. Это возможно осуществить путем настройки приложения так, чтобы оно, например, стало DOM-со- DOM-совместимым. У?ЕСУРС ' • .<-Ч .. ; , ,-,,,-, ,- . _,0. ,; По адресу www.w3.org/TR/i999/CR-DOM-Level-2- 19991210 находится "W3C Document Object Model (DOM) Level 2 Specification". Более ранняя специфи- спецификация уровня Level 1 также находится на этом сайте. Информация, содержащаяся в спецификации, не пе- передается непосредственно в JavaScript или другой ЕСМА-совместимый язык создания сценариев. Прило- Приложение Е спецификации показывает привязку к соот- соответствующему ECMAScript языку. В Web появилось большое количество учебников по DOM и множество сопроводительных статей и документов. От DHTML к DOM Приведение Web-страниц к объектной модели имеет много стадий, но самая существенная из них — DHTML, который сом по себе является довольно незначащим по сравнению с D0M. Это потому, что D0M — стандарти- стандартизированная объектная модель, которую Web-разработчи- Web-разработчики ждали очень долго. Например, если Web-разработчик должен будет модифицировать или настраивать Web-
Использование DOM Часть III страницу с помощью объектной модели DHTML, ему в качестве руководства потребуется значительный объем информации. Причина этому — огромное число HTML- дескрипторов, свойств, методов и событий. DHTML дей- действительно не больше, чем средства, позволяющие из- изменять и управлять объектами с помощью атрибутов id и name. Это далеко от стандартизации и упрощения DOM, которая инкапсулирует целый документ в объек- объектную модель, представляя его в виде иерархии или де- дерева. Узлы дерева представляют собой HTML-деск- HTML-дескрипторы и текстовые сегменты, которые они могут содержать. Полный HTML-документ хранится в этом дереве, а все объекты и их отношения отображаются как дочерние и родительские элементы, а также элементы одного уровня. В отличие от DHTML, управлять и вно- вносить изменения в DOM-дерево документов весьма не- несложно. Для изменений текстовых элементов, например, просто изменяют значения узла дерева с помощью свой- свойства nodeValue. Кроме того, существует возможность создавать, удалять и перемещать узлы в дереве DOM- документа. (Методы, которые позволяют это делать, описываются позже, в табл. 13.2.) Навигация по таблице Для того чтобы лучше понять структуру дерева, рассмот- рассмотрим структуру DOM-дерева простой таблицы (см. рис. Таблица 13.1. Выражения для навигации. 13.1). Здесь показаны свойства childNodes, flrstChild, lastChild, nextSibling и previousSibling. Используем их, чтобы понять структуру дерева и научиться перемещать- перемещаться к любой его части. В DOM-дереве таблицы <table> будет находиться в корне дерева. Из этого следует, что можно двигаться в любой пункт дерева, определяя соответствующий узел. Двигаясь вниз по дереву, достигнуть различных его частей можно с помощью выражений, показанных в табл. 13.1. Управление документами Рассмотрим некоторые основные методы DOM, кото- которые позволяют исполнять часто встречающиеся задачи. В своем API DOM определяет методы, которые долж- должны создавать, удалять, вставлять, перемещать, менять местами и заменять узлы или объекты. Эти методы и их аргументы, описания и возвращаемые значения, или исходящие параметры, кратко описаны в табл. 13.2. Фак- Фактически, все это довольно очевидно; метод removeNode() удаляет поддерево, встроенное в указанный узил, если deep равно true. Если же deep — false, удаляется только указанный узел, а его дочерние объекты возвращаются текущему родительскому элементу предыдущего уровня. Другой метод, зависящий от логического параметра, — cloneNode(). Когда параметр равен true, копируется под- поддерево, а когда он — false, копируется только узел. Перемещение Выражение Ко второй строке таблицы. К первой ячейке второй строки. К содержимому второй ячейки в первой строке. К корню второй строки. К каждой из ячеек и затем возврат в корень. К каждой из ячеек. tablel\lode.firstChild.childNodes[1] tableNode.firstChild.childNodes[1].childNodes[0] tableNode.firstChild.firstChild.childNodes[1].firstChild Tr2Node.parentNode.parentNode или Tr2Node. previousSibling.parentNode.parentNode или Tr2Node.previousSibling.previousSibling.parentNode.parentNode tableNode.firstChild.firstChild.firstChild.firstChild.parentNode.parentNode. parentNode.parentNode tableNode.firstChi!d.firstChild.childNodes[1].firstChild.parentNode.parentNode. parentN ode. parentN ode tableNode.firstChild.childNodes[1].firstChild.firstChild. parentNode.parentNode. parentN ode. parentN ode tableNode.firstChild.childNodes[1].childNodes[1].firstChild.parentNode.parentNode. parentNode. parentNode tableNode.firstChild .firstChild .firstChild. firstChild tableNode.firstChild.firstChild.childNodes[1].firstChild tableNode.firstChild.childNodes[1].firstChild.firstChild tableNode. firstChild.childNodes[1].childNodes[1].firstChild
Основы объектной модели документа (DOM) Ш9Я Глава 13 РИСУНОК 13.1. Простая структура DOM-дерева таблицы. |childNodes[1] II Or lastChild I I chlldNodeejO] I [chlldNoites|11 § QrtasLChiW I Таблица 13.2. Методы DOM для управления документами. Синтаксис метода DOM Аргумент или параметр Описание AppendChild fatherObj.appendChild(childObj) Объект ApplyElement childObj.applyElement(fatherObj) Объект ClearAttributes clearedObj.clearAttributes() He имеет CloneNode newObj =existingObj. cloneNode(deep) Логический CreateElement newObj = document. HTML- createElement("Tag") дескриптор CreateTextNode newObj = document. Строка createTextNode(string) HasChildNodes hasChildrenFlag = testedObj. He имеет hasChildNodesQ InsertBefore parentObj.insertBefore(childObj, brotherbbj) Объект MergeAttributes targetObj.mergeAttributes(sourceObj) Объект RemoveNode deletedObj.removeNode(deep) He имеет ReplaceNode oldObj.replaceNode(newObj) Объект SwapNode firstObj.swapNode(secondObj) Объект Добавляет дочерний объект (childObj) к родительскому объекту (fatherObj). Направляет элемент объекта к другому объекту (fatherObj). Удаляет все атрибуты и значения объекта (clearedObj). Копирует существующий объект для создания нового (newObj). Создает узел (newObj) для нового дескриптора. Создает новый текстовый узел (newObj). Определяет, имеет ли объект дочерние элементы. Вставляет объект (childObj) как дочерний элемент для (parentObj). Объединяет все атрибуты (sourceObj) в (targetObj). Удаляет поддерево объекта, если deep равно true, и только узел, если deep — false. Заменяет узел (oldObj) новым (newObj). Меняет местами один узел с другим. Объектная модель и атрибуты иерархиями, показывая все их связующие ссылки. Но соглашение DOM не требует представления документов Структура DOM-документа может, фактически, ВКЛЮ- в виде деревьев, а также не требует наличия определен- чать множество деревьев, являющихся объектными НЫХ отношений между объектами. Однако, каждый до-
Использование DOM Часть III кумент должен иметь узел типа документа, корневой узел элемента, служащий корнем дерева документа, а также комментарии или инструкции по обработке. Пред- Представление в виде дерева, или структурная модель, имеет информационные элементы, к которым обращаются, используя методы перемещения по дереву. DOM также твердо придерживается структурного изоморфизма, в ко- котором различные DOM-совместимые реализации при создании представления одного и того же документа приводят к идентичной структурной модели. Узлы, об- обсуждавшиеся выше, имеют различные атрибуты, многие из которых перечислены в табл. 13.3. ПРИМЕЧАНИЕ . ,з а. ".¦ '" ';'*.¦ ... Й Изменение префикса атрибута, который принимает значение по умолчанию, не создает новый атрибут с этим значением по умолчанию и первоначальным пре- префиксом, если namespaceURI и localName не менялись. Таблица 13.3. Часто используемые атрибуты DOM. Навигация по документу Рассмотрев, как управлять простой таблицей, вполне естественно перейти к тому, как делать то же самое с до- документом. Листинг 13.1 показывает DOM-структуру, ко- которая содержит заголовок документа, текстовый блок и четыре параграфа: Листинг 13.1. Простой документ. <HTML> <HEAD> <TITLE> DOM document tree </TITLE> </HEM» <BODY ID=[dbl]bodyNode[dbl]XP ID = "Nodel">A first paragraph</P> The main document <P ID = [dbl]Node2[dbl]> <P ID = [dbl]Node3[dbl]X/P> <P ID = [dbl]Node4[dbl]X/P> </BODY> </HTML> Атрибут Чтение/запись Описание Атрибуты типа NamedNodeMap Только для чтения childNodes типа NodeList firstChild типа Node lastChild типа Node localName типа DOMString Только для чтения Только для чтения Только для чтения Только для чтения namespaceURI типа DOMString Только для чтения nextSibling типа Node Только для чтения nodeName типа DOMString Только для чтения nodeType типа unsigned short Только для чтения ownerDocument типа Document Только для чтения parentNode типа Node Префикс типа DOMString previousSibling типа Node Только для чтения Только для чтения NamedNodeMap содержит атрибуты узла. NodeList содержит все дочерние элементы узла. Первый дочерний элемент узла; если узел не существует, возвращается Null. Последний дочерний элемент узла; если узел не существует, то возвращается Null. Возвращает локальную часть составного имени данного узла. Когда используется с узлами, созданными с помощью метода DOM первого уровня, включая createElement, то возвращает значение Null. Содержит данное значение namespaceURI. Это — всегда Null для узлов всех типов, кроме ElementNode или Attribute Node. Это Null для узлов, созданных методом DOM первого уроаня, включая createElement из интерфейса Document. Следующий узел в последовательности; когда следующего узла не существует, возвращается Null. Имя узла. Код, содержащий определенный тип объекта. Объект Document, который принадлежит узлу; этот объект Document используется для создания новых узлов. Родительский элемент узла. Это — не Attr, Document, Document Fragment, Entity или Notation. ParentNode будет равен Null, если узел недавно создан и только должен стать частью дерева, либо если он удален из дерева. Префикс пространства имен узла; возвращается пустой указатель, если ничего не определено. Установка этого атрибута заменяет атрибут nodeName, который содержит составное имя tagName и атрибуты имен интерфейсов Attr и Element. Следующий из предыдущих узлов; когда такой узел не существует, возвращается Null.
Основы объектной модели документа (DOM) Дескриптор <body> находится на верхнем уровне дерева и имеет пять дочерних элементов: четыре деск- дескриптора <Р> и одиночный текстовый блок. DOM-дере- DOM-дерево документа имеет узлы для дескрипторов и текстовых Таблица 13.4. Навигация по документу. Глава 13 блоков. Можно управлять деревом из узлов, которые имеют атрибуты ID. Используя свойства DOM, можно перемещаться к любому пункту в документе (см. табл. 13.4). Перемещение Выражение К первому дочернему элементу. Ко второму дочернему элементу. К четвертому или последнему дочернему элементу. Ко второму дочернему элементу корня (текстового узла) от узла 1. IK третьему дочернему элементу корня от узла 1. К последнему дочернему элементу корня. К дочерним элементам четвертого дочернего элемента. Ко второму дескриптору <Р> от третьего <Р>. К дочернему элементу дескриптора <body>. К дескриптору корня <body> от дескриптора <Р>. К дочернему элементу <body> и возврат к <body>. bodyNode.firstChild или bodyNode.childNodes[0] bodyNode.childNodes[1] bodyNode.childNodes[4] или bodyNode.lastChild Nodei.nextSibling Nodei .nextSibling.nextSibling Nodei .nextSibling.nextSibling. nextSibling Nodei .nextSibling.nextSibling. nextSibling.childNodes[0] Node3.previousSibling. previous Sibling. previousSibling.cnildNodes[0] bodyNode.firstChild.firstChild Nodei .parentNode body Node.firstChild.firstChild. parentNode. parentNode Резюме В главе рассматривались основные принципы DOM, a также базовая объектная модель, применимая к стандар- стандартным объектам простых Web-страниц. Были показаны методы навигации и способы перемещения между узла- узлами, определяющими документы. Кроме того, рассматри- рассматривались свойства, их изменения и использование для получения информации с помощью модели дерева. При- Приводилась терминология DOM, например, узлы с имена- именами типа firstChild, lastChild, nextSibling и previousSibling. С этой основной информацией теперь можно подроб- подробно остановиться на приложении DOM в контексте JavaScript. В главе 19 DOM исследуется более подроб- подробно.
Управление событиями в этой главе Понятие событий и обработчиков событий Обработчики событий JavaScript Обработка ошибок (опЕгтог) Прерывание загрузки изображения (onAbort) Замена обработчиков событий Программная генерация событий События таймера Если в последние несколько лет вы много занима- занимались программированием, скорее всего, вы использова- использовали язык программирования, управляемый событиями. Процедурные программы из прошлого диктовали, какие задачи пользователю ИСПОЛНЯТЬ в любой заданный мо- момент времени. Однако, графические оконные среды сегодня имеют совершенно другую парадигму и требу- требуют, чтобы прикладные программы, в первую очередь, отвечали на инициированные пользователями события. Памятуя об основанном на объектах характере JavaScript (см. главу 9) можно ожидать, что JavaScript является прежде всего управляемым событиями языком. Эта глава рассматривает JavaScript-события и способы ответа на них, т.е. создание на сайте интерактивных сце- сценариев. Понятие событий и обработчиков событий Многие из кодов JavaScript отвечают на события, выпол- выполненные пользователем или программным обеспечением браузера. Эта управляемая событиями среда позволяет разработчику сосредотачиваться только на событиях, которые затрагивают его приложение; то, что браузер исполняет между событиями — дело браузера, а не раз- разработчика. Кроме того, разработчику не нужно интере- интересоваться всеми событиями, выполненными пользовате- пользователем — лишь только теми, которые требуют ответа. Каждое JavaScript событие имеет соответствующий обработчик событий (event handler), который предназна- предназначен для автоматического ответа на происходящее собы- событие. При работе с событием к нему не добавляют код и не изменяют его непосредственно, а, скорее, управляют обработчиком события, которому данное событие соот- соответствует. Обработчики событий JavaScript Разработчикам HTML-страниц известно, что каждый элемент в форме имеет дескриптор и связанный с ним атрибут. Например, ввод текста определяется следующим способом: <input type=text size=30 maxlength=30 name="LastName"> JavaScript реализует обработчики событий, встраивая их в качестве атрибутов HTML-дескрипторов. Напри- Например, предположим, что необходимо выполнять создан- созданный метод каждый раз, когда значение объекта Text изменяется. Для этого придется присвоить метод (с име- именем, например, checkField()) обработчику событий onChange объекта Text: <input type=text size=30 maxlength=256 name="LastName" onChange="checkFieldC this ) "> В кавычках можно записывать непосредственно JavaScript-код или же вызов отдельной функции. Хотя предыдущий пример вызывает функцию checkFieldQ, следующий код также допустим: <input type=text size=30 maxlength=256 паю-1 Las tName " onChange= "if ( confirm( 'Are you certain '^•you wish to change this value?')) { alert('Changed' )}" > При использовании встроенного кода можно разме- размещать сразу несколько строк в пределах назначения об- обработчика событий, применяя точку с запятой для от- отделения друг от друга операторов JavaScript. Однако, множество строк программы следует применять с ос- осторожностью. Намного проще работать с кодом, вы- выделенным в функцию, а не с находящимся непосред-
Управление событиями ственно внутри обработчика событий. Например, если весь код физически расположить в одном месте, из- изменения делать в нем окажется намного удобнее. Далее в главе исследуются самые распространенные события, поддерживаемые как Microsoft Internet Explorer, так и Netscape Navigator. Особое внимание уделяется наиболее часто используемым событиям. Для этого бе- берется типичная HTML-форма (см. рис. 14.1) и добавля- добавляется код в ее обработчики событий. Форма, которая бу- будет использоваться на первых порах — обобщенная форма заказа для некоторой виртуальной компании. Щелчок на объекте (onClick) Одна из наиболее общих целей JavaScript — расширение HTML-формы и достижение таким способом большей степени взаимодействия с пользователем. Если это так, возможно, единственное наиболее частое событие, с которым будет работать большинство разработчиков, — это событие click. Событие click вызывается, когда пользователь щелкает на каком-либо объекте, предназ- предназначенном для нажатия. Для большинства компьютерных сред событие click вызывается только после того, как заданная по умолча- умолчанию кнопка мыши нажата и отпущена. Пользователь, который будет держать кнопку мыши и не отпустит ее на объекте, событие click объекта не вызовет. Когда событие click происходит, обработчик событий onClick для нажатого объекта выполняет одну (или боль- больше) JavaScript-команд либо вызывает определенную функцию. Например, посмотрим на кнопку "View Hat" на рис. 14.1. Предположим, что необходимо добавить код, который при нажатии этой кнопки отобразит еще одно окно браузера с изображением шляпы. В HTML объект Button определяется следующим образом: <input type=button name="ViewHat" value="View Hat" onClick="displayHat() "> Legeiitt of Kakatn Hat Order Form Jfyerti/ouldlikefflWt inforamnaihthe I.^f faaowb^foreft. Ц lll«'to!eeii<teBl«<lp««muf*.tUs«aJofK»kai^atbeEorraJ»rltis.pt.iHcld Custoirer Information! Lu С M i С .HVW! L. ¦ Глава 14 В разделе <bead> HTML-файла записывается метод (lisplayHat(), который будет вызываться при вызове об- обработчика событий кнопки onClick: <head> <script language="JavaScript"> <! — //Обработчик событий onclick function displayHat() { hatWindow = window.openf'http:// '-•www.myhat.com" , "view MyHafc" , "toolbar=0, width=20O,height=40O,resizable=0") ; ) </script> < /head> Когда пользователь нажимает кнопку, обработчик событий использует метод ореп() объекта Window для вывода на дисплей окна, содержащего изображение шляпы (см. рис. 14.2). Обработчик событий OnClick существует не только для кнопок; его можно использовать для ответа на вклю- включение флажков, выбор переключателей и щелчка на объектах Link. Из-за характера этих элементов управле- управления настройка их события click встречается редко. Флаж- Флажки и переключатели часто используются для ввода дан- данных и вычисляются после выполнения на них щелчка. Что касается объекта Link, то он используется прежде всею как ссылка на расположение, указанное в его свой- свойстве href, и в добавлении кода часто нет необходимос- необходимости, если только не нужно менять его заданное по умол- умолчанию поведение. | : View lisri ; ¦ ¦¦¦ j ¦ io«..iv: 1 ...i i rta Eftn >Ji -;.¦ - ¦ j_ ui1 ¦ '- i Hat Order Form of ti\t Legend cflltiBiii Ait tci'-лг ¦¦: Jem ¦ j. ркмс oft* Uk f-Ji dfS| 'РИСУНОК 14.2. С помощью метода ореп() отображается второе окно. ПРИМЕЧАНИЕ РИСУНОК 14.1. Например HTML-формы. Для флажков, ссылок, переключателей, а также для кнопок "Reset" и "Submit" можно возвращать значе- значение false от обработчика событий onClick, чтобы от- отменить вызванное действие. Например, если нужно подтвердить, действительно ли выставлен флажок, в
Использование DOM Часть III его обработчик событий onClick добавляется следую- следующий код: <input type="checkbox" name="checkboxl" value="DeluxeRoom" pnClick="return confirm('Deluxe rooms are very '-•expensive. Are you sure?') ">Deluxe Room Поскольку вид Web-страницы также важен, для от- ответа на события click вместо кнопок лучше использовать изображения. Хотя изображение не способно фактичес- фактически ответить на любое событие, можно имитировать со- событие click с помощью объекта link. Продемонстриру- Продемонстрируем это, используя изображение вместо кнопки "View Hat" для вызова метода disp!ayHat() из предыдущего приме- примера. Для этого определим соответствующий объект Link: <href в "JavaScript :displayHat () "> <img sro = "minihat.gif" align=bottam border=Q width=89 height=75> Вместо добавления кода в обработчик события onClick ссылки, здесь используется JavaScript в качестве протокола для свойства href. Использование JavaScript: JavaScriptExpressioitKSiK значение свойства href застав- заставляет браузер выполнить выражение JavaScript вместо перехода к определенной ссылке. Отправка формы (onSubmit) Как обсуждалось в главе 1, одно из преимуществ исполь- использования JavaScript в HTML-формах — возможность вы- выполнения проверки правильности данных на стороне клиента вместо перекладывания этой задачи на и без того перегруженный сервер. Проверку правильности можно выполнять для каждого поля в отдельности или для всех полей сразу. В зависимости от контекста ис- используется один или оба метода. Для проверки правильности данных во всех полях сразу, равно как и для других задач, главное значение имеет событие submit. Это событие генерируется как раз перед отправкой HTML-формы. Добавление кода в об- обработчик событий onSubmit объекта Form дает возмож- возможность совершить проверку, а затем разрешить продолже- продолжение или блокировать его, уведомив об этом пользователя. Событие submit произойдет, если от обработчика событий onSubmit не возвращается значение false. Лю- . бое другое значение (true или еще что-нибудь) приве- приведет к генерации этого события. Например, предполо- предположим, что перед отправкой формы на сервер необходимо отобразить простое сообщение для пользователя с просьбой подтвердить заполнение формы заказа шляпы Kakata. Форма в HTML определяется следующим обра- образом: <form action="process.cgi" method="POST" onSubmit="return confirmOrder () "> Метод confirmOrderQ, используемый в обработчике событий onSubmit формы, объявляется в разделе <head> файла: //обработчик событий onSubmit function confirmOrder() { return confirm ('Are you certain you wish to border the Kakata hat?') ; )' При включении метода confirmOrder() он отобража- отображает диалоговое окно Confirm с кнопками "ОК" и "Cancel". Если пользователь нажимает на "ОК", диалоговое окно закрывается и в обработчик событий onSubmit возвра- возвращается значение true. Если пользователь нажимает на '"Cancel", возвращается false. Оператор return в обработ- обработчике событий onSubmit исследует входящее значение и определяет, нужно ли продолжать обработку формы. Оператор return в назначении обработчика событий не- необходим для корректной работы кода. Присваивание обработчику событий onSubmit = "confirmOrder()" запус- запускает обработку формы независимо от возвращенного из диалогового окна значения. Обработчик событий onSubmit — то же самое, что и обработчик событий onClick объекта Submit. Оба они — события, которые можно использовать, чтобы захва- захватить форму прежде, чем она будет обработана. Как по- показано на рис. 14.3, обработчик событий onClick объекта Submit был вызван до вызова обработчика onSubmit формы. Form OnClick No Yes Return OnSubmit No yes Return ACTION РИСУНОК 14.3. Установление последовательности событий для отправки формы. Обработчик событий onSubmit — идеальное место для размещения проверки правильности данных формы до ее отправки на сервер. Сброс формы (onReset) Может понадобится вызвать событие и при сбросе фор- формы, а не только при отправке. Обработчик событий onReset вызывает код JavaScript, когда происходит собы-
Управление событиями Глава 14 тие reset. Так же, как onSubmit, onReset — обработчик событий объекта Form. Для демонстрации этого снова рассмотрим форму заказа шляпы Kakata, упомянутую в прошлом разделе. После добавления нового обработчика событий к опре- определению объекта Form код будет выглядеть так: <form action="process.cgi" method="POST" onSubmit="return confirmOrder<)" onReset="return confirmReset () "> Мегод confirmReset(), используемый в обработчике событий onReset формы, объявляется в разделе <head> файла: //обработчик событий onReset function confirmReset () { return confirm ('Are you certain you wish to ¦"¦clear the order form? ' ) ; 1 примечание'':<*"У?'Ц>>-;;~~ -v^ ; :.^ ¦ yj-^- Обработчик событий onReset поддерживается в JavaScript t.t и более поздних версиях. Изменение данных (onChange) Как упоминалось в связи с событием submit, если при- прикладные программы JavaScript имеют дело с данными, обычно возникает необходимость в предварительной обработке данных, введенных пользователем, во избежа- избежание проблем проверки допустимости при отправке дан- данных серверу. В то время как submit служит для провер- проверки сразу всех полей формы, событие change обычно наиболее важно для проверки допустимости на уровне каждого поля формы. Событие change происходит, ког- когда изменяется значение объектов поля и когда само поле выходит из фокуса. Для решения такого рода задачи используется обра- обработчик событий onChange для выполнения JavaScript- кода либо вызова функции для обработки события. Предположим, что необходимо добавить базовую под- подпрограмму проверки допустимости данных в форму вво- ввода данных для заказа шляпы Kakata. Скажем, требуется гарантия того, что содержимое поля "State" записано буквами верхнего регистра. Объект Text определяется следующим образом: <input type=text size=3 maxlength=2 name="State" onChange="convertToUppercase{this)"> M етод convertToUppercase() преобразовывает значе- значение поля "State" к верхнему регистру, используя метод toUpperCase() строки: function convertToUppercase (fieldObject) ( fieldObject.value = fieldObject.value.toUpperCase{) Получение фокуса (onFocus) Событие focus вызывается, когда объект поля получает фокус, т.е. когда пользователь переходит к объекту с использованием клавиши "Tab" или с помощью щелчка мыши на объекте, либо когда вызывается метод focus() объекта. В каждый момент времени фокус может иметь только один объект. ПРИМЕЧАНИЕ ''^^"¦" _ _ JavaScript 1.1 и последующие версии расширяют воз- возможности onFocus, включая его в качестве обработ- обработчика событий для объектов Window, Frame и Frameset. Для каждого из этих объектов обработчик событий onFocus определяет действие, которое должно выпол- выполниться при переходе фокуса. Обработчик событий OnFocus должен размещаться внутри дескрипторов <body> объектов Window, Frame или Frameset. Обработчик событий onFocus в этих объекта может отвечать за переключение действия. Например, он мо- может расширять стандартное поведение объектов Text в форме. При переходе к объекту Text курсор появляется по умолчанию. Однако, во многих средах (например, в Windows), если поле уже имеет значение, то при уста- установке фокуса на объект содержимое поля выделяется. Для получения такого поведения (см. листинг 14.1) по- потребуется добавить обработчики событий onFocus каж- каждому из объектов Text и Textarea: Листинг 141. Использование события onFocus для полей формы. <pre> First Name: <input type=text size=20 maxlength=20 name="FirstName" onFocus="selectContents(this)"> Last Name: < input type=text size=20 maxlength=20 name="LastName" onFocus="selectContents(this) "> Title: <input type=text size=30 maxlength=25 6 name="Title" onFocus="selectContents(this)"> Company: < input type=text size=30 maxlength=256 name="Company" onFocus="selectContents(this) "> Street Address: <input type=text size=30 maxlength=2 56
Использование DOM Часть III name="StreetAddr" onFocus="selectContents(this)"> City: <input type=text size=30 raaxlength= 256 name="City" onFocus="selectContents(this) "> State: <input type=text size=3 maxlength=2 name="State" onFocus="selectContents(this)" onChange="convertToUppercase(this)"> Zip Code: <input type=text size=30 maxlength=10 name="Z ipCode" onFocus="selectContents(this) "> Telephone: <input type=text, size=12 maxlength=12 name="Phone" onFocus="selectContents(this)"> FAX: <input type=text size=12 maxlength=12 name="FAX" onFocus="selectContents(this)"> E-mail: <input type=text size=30 maxlength=25 6 name="Email" onFocus="selectContents(this) "> DM.: <input type=text size=30 raaxlength=256 name="URL" onFocus="selectContents (this) "x/pre> <textarea name="worthyBox" rows=3 cols=49 onFocus="selectContents(this)"> </textarea> Хотя можно написать отдельные обработчики собы- событий для каждого из полей, это будет нерациональным подходом, если только процессы не оказываются совер- совершенно разными. Вместо этого в методе seIectContents() пользуются преимуществом ключевого слова this для ссылки на вызывающий объект. Приведенная ниже фун- функция тогда будет использоваться в качестве глобальной для всех объектов: function selectContents (fieldObject) ( FieldObject.select() ; ) Когда один из объектов Text или Textarea вызывает метод selectContentsQ, метод использует параметр fieldObject как ссылку на вызывающий объект. Затем метод select() осуществляет выбор информации в обла- области ввода указанного объекта. Выход из фокуса (onBlur) Событие blur (противоположность события focus) вызы- вызывается, когда объект теряет фокус. «ПРИМЕЧАНИЕ ~" iW^f^t s Как и с обработчиком событий onFocus, JavaScript 1.1 и последующие версии расширяют возможности onBlur, включая его в качестве обработчика событий для объектов Window, Frame и Frameset. Для каж- каждого из этих объектов обработчик событий onBlur определяет действие, которое должно выполниться, когда окно теряет фокус. Обработчик событий OnBlur должен помещаться в дескриптор <body> объектов Window, Frame или Frameset. Например, предположим, что для формы ввода дан- данных нужна гарантия, что пользователь не оставил пус- пустым объект EmailText. Такую проверку можно добавить в обработчик событий onBlur данного объекта. Посколь- Поскольку она воздействует на одно поле формы, можно доба- добавить JavaScript-код только к определению объекта Text: <input type=text size=30 maxlength=256 ijame="Email" onFocus="selectContents(this)" onBlur="if (this, value = ¦'){ alert ('You must enter ^something. ') ;this.focus();)"> Если пользователь попытается убрать фокус из объекта без ввода текста в данное поле, сигнальное ди- диалоговое окно уведомит о недопустимости. Следующая команда возвращает фокус к объекту EmailText. Без этой команды курсор перешел бы к следующему полю. Несложно заметить, что onChange и onBlur — очень похожие обработчики событий. Возникает вопрос о том, когда нужно использовать один, а когда другой. OnChange больше подходит для проверки или анализа содержимого объекта и обладает преимуществом в том, что не вызы- вызывается при изменении значения пользователем. С дру- другой стороны, для обязательных полей лучше использо- использовать onBlur. Важно понять правильный порядок следования об- обработчиков событий onChange, onBlur и onFocus. Как показано на рис. 14.4, onFocus происходит при входе в поле. При выходе из него вызывается onChange, затем onBlur и, наконец, обработчик onFocus следующего входного объекта. Имейте в виду, что код, который до- добавляется (например, в обработчик событий onChange), может воздействовать на обработчик событий onBlur того же самого объекта. Другими словами, использовать эти три события следует с особой осторожностью.
Управление событиями First Name First Name onFocus onChange \/ onBlur L onFocus РИСУНОК 14.4. Порядок следования событий от одного объекта Text до другого объекта Text. Выделение текста (onSelect) Следующее JavaScript событие — событие select, кото- которое происходит, когда пользователь выделяет текст в объекте Text или Textarea. Обработчик событий onSelect этих объектов выполняет JavaScript-код или вызывает указанную функцию. Независимо от способа реализации, возможности события select довольно ограничены, и большинству разработчиков оно вообще может не понадобиться. .Перемещение мыши по объектам (onMouseOver и onMouseOut) Опытный пользователь Web, вероятнее всего, будет ожи- ожидать, что перемещение мыши по тексту ссылок отобра- отобразит место назначения ссылки (обычно URL-адрес). Од- Однако, несмотря на то, что опытные пользователи хотят видеть URL-адрес, начинающие пользователи предпоч- предпочли бы вместо этого увидеть нечто менее прозаическое. Это особенно актуально в intranet-средах, где URL-ад- URL-адрес обычно значительно менее понятен. Захват событий Листинг 14.2. Исходный код для Register.htm. Глава 14 mouseOver и mouseOut позволяет изменять в строке со- состояния текст по умолчанию. ^ПРИМЕЧАНИЕ s «f» ¦ Vv!^^*»}',----^ ¦;' ¦ .:,. ,%g Обработчики событий onMouseOver и onMouseOut также поддерживаются объектом Area в JavaScript 1.1 И последующих версиях. Событие mouseOver генерируется, когда пользователь помещает курсор мыши поверх объекта Link или Area. Как и следовало ожидать, onMouseOut ведет себя таким же образом, за исключением того, что событие проис- происходит, когда курсор уводится из Link или Area. Обработ- Обработчики событий onMouseOver и onMouseOut этих объек- объектов могут затем изменять заданное по умолчанию поведение браузера. Если необходимо установить свой- свойства status и defaultStatus окна, следует возвратить в об- обработчик событий значение true. Например, предположим, что требуется отобразить следующий текст в строке состояния, когда для ссылки на шляпу Kakata генерируется событие mouseOver: Click here to get the whole story about the Legend of Kakata . Для отображения данного текста добавьте в дескрип- дескриптор Link обработчик событий onMouseOver: <а href="http://www.kakata.com" name="linker" onMouseOver="returnupdateStatusBar ( ) " >Legend of Kakata Метод updateStatusBar() определяется таким обра- образом: // обработчик событий onMouseOver function updateStatusBar {) { window, status = 'Click here to get the whole ^* story about the Legend of Kakata' ; return true II Все рассмотренные в главе примеры содержатся в файле Register.htm. Листинг 14.2 дает полный исходный код для этих примеров. <html> <head> <title>Kakata Hat Registration</title> <script languages"JavaScript"> var noticeWindow //Обработчик событий onclick, function displayHat() { hatwindow=window. open f "http: / , . /kakata/viewhat. htm" , "ViewHat" /"toolbar=0,width=200,height=400,resizable=0") //Обработчик собыгш on Submit 7 1-158
Использование DOM Часть III function conf irmOrder ( ) return confirm ('Are you certain you wish to order the Kakata hat?'); 1 //Обработчик событий onChange function convertToUppercase ( f ieldObject) { fieldObject.value =f ieldObject.value,toUpperCase <); ] ./ / Обработчик событий onFocus function selectContents(f ieldObject) { fieldObject.select() ; 1 / / обработчик событий onMouseOver function updateStatusBar () { window, status = 'Click here to get the whole story about the Legend of Kakata1 return true } // обработчик событий onMouseOut .function updateStatusBarOut() { window, status = ' ' ,- return true ] // Обработчик событий onSelect function accessText () { alert ( ' Success" ) ; 1 // —> </script> </head> <body baekground="lt_rock.gif"> <hlxfont color="#008000">Legend of Kakata Hat Order FornK/fontX/hl> <hr> <p>If you would like more information on the <ahref="http: //www, acadians.com/javascript/kakata/kakata.htm" name="linker" onMouseOver="return updateStatusBar() " onMouseOut="return updateStatusBarOut () ">Legend of Kakata </a>, please fill out the following form. </p> <form method="POST"> ¦<p>If you would like to see a detailed picture of the Legend of Kakata Hat before ordering, please click the following button: <input type=button name="ViewHat" value="View Hat" onClick=displayHat () X/p> </form> <hr> <?orm action="JavaScript: alert(' order' ) " method="POST" name="MainForm" onSubmit="return confirmOrder () "> <h2Xfont color="#008000">Customer Information</fontx/h2> <pre> First Name: <input type=text size=20 maxlength=20 name="FirstName" onFocus="selectContents(this)"> Last Name: <input type=text size=20 maxlength=20 name="LastName" onFocus="selectContents(this)"> Title: <input type=text size=30
Управление событиями Company: <input Street Address: <input City; <input State : <input maxlength=30 name="Title" onFocus="selectContents(this)"> type=text size=30 maxlength=30 name="Company" onFocus="selectContents(this)"> type=text size=30 maxlength=30 naroe="StreetAddr" onFocus="selectContents (this)"> type=text .size=30 maxlength=30 name="City" onFocus="selectContents (this) "> type=text size=3 maxlength=2 name="State" onFocus="selectContents(this)" onChange="convertToUppercase (this)"> Zip Code: <input Telephone: <input FAX: <input Email : <input size=30 URL : < input type=text size=30 maxlength=10 name="ZipCode" onFocus="selectContents(this)"> type=text maxlength=12 name=" Phone" onFocus="selectContents (this) "> type=text size=12 maxlength=12 name="FAX" onFocus="selectContents (this) "> maxlength=50 name="Email" onFocus="selectContents(this)"> type=text size=30 maxlengtbOl О <hr> onFocus="selectContents (this) "X/pre> Глава 14 <pXstrong>Are you Squot; Kakata worthySquot;? Please use the space below to enter a thorough reason for your order .</strongX/p> <blockquote> <pXtextarea riame= "worthy Box " rows=3 ¦cols=49 onFocus="selectContents(this)"> </textareaX/blockquoteX/p>
Использовонш DOM Часть III <h2Xfont color="#008000">Form Submission</f ontX/h2> <pXen»Please click the Order button to order your free Legend of Kakata hat. You will receive email confirmation of your order in 24 hours.</emX/p> <pXinput type=submit value="Order" onClick="confirmOrder('Submit object')"> <input type=reset value="Clear Fonn" onClick="alert('Clearing! ')"X/p> <p>snbsp;</p> <P> </form> href="JavaScript:displayHat()"> <img src="ball.gif" align=bottom border=0 width=16 height=16> </body> </html> СОВЕТ При захвате множества событий mouseOver и mouse в объекте Area обработчик событий onMouseOut вызывается при уходе из этой области, затем при вхо- входе в следующую область вызывается on MouseOver. Загрузка документа (onLoad) 1ачальнос открытие окна или фрейма может оказаться важным моментом времени для выполнения определен- определенного JavaScript-кода. Событие load позволяет использо^ вать этот момент, добавляя обработчик событий onLoad к дескриптору <body> в случае однофреймового окна или к дескриптору <frameset> в случае мультифреймо- вого окна. Событие load выполняется, когда браузер за- завершает загрузку окна или всех фреймов мультифрей- мового окна. Объект Window — единственный объект, который может работать с этим событием. В качестве примера рассмотрим ситуацию, когда нужно гарантировать, что все пользователи intranet-сети некоторой компании используют требуемую версию Netscape Navigator. Для этого можно определить брау- браузер, применяемый обработчиком событий onLoad и за- затем уведомить пользователя, правильная ли у него вер- версия программы. В дескриптор <body> документа добавляют обработчик событий onLoad: <body i Затем в дескрипторе <head> документа определяет- определяется метод checkBrowser(): //обработчик событий onLoad function checkBrowser() { if 'Netscape') ss (navigator.appVersion = '4.0 (Win95; I)')> { noticeWindow = window. open ("" , "NoticeWindow'1, "toolbar=0,width=300,height=100,resizable=0"); noticeWindow. document, write <"<headXtitle>Upgrade l-(Notice</titleX/head>") ; int.write ("<ce *"*Web Browser needs to be updated. Pleas< e your supervisor before noon. ^</bX/bigX/center>")) Сразу после загрузки документа выполняется JavaScript- метод. На рис. 14.5 показан вид окна Upgrade Notice для версий, не прошедших испытания. РИСУНОК 14.5. Окно UpgradeNotice открыто с помощью обработчика событий onLoad. ПРИМЕЧАНИЕ У объекта Image также есть обработчик событий onLoad. Это событие вызывав' ся, когда браузер вы- выводит на дисплей изображение. Обратите внимание, что данное событие происходит не в процессе загруз-
Управление событиями Глава 14 ки изображения клиенту, а в течение вывода на дисп- дисплей этого изображения. Выход из документа (onUnload) Событие unload (противоположное событию load) вы- вызывается непосредственно перед выходом пользователя из документа. Как и в случае с onLoad, обработчик событий ¦onUnload можно добавлять в дескриптор <body> в случае однофреймового окна или в дескриптор <frameset> в слу- случае мультифреймового окна. Если есть мулътифреймовое окно и множество обработчиков событий onUnload для фреймов, то обработчик событий мультифреймового окна всегда выполняется в последнюю очередь. Приведем пример использования обработчика собы- событий onUnload для очистки среды браузера перед перехо- переходом к следующей странице. Например, предположим, что требуется закрыть окно View Hat при уходе со стра- страницы заказа шляпы Kakata. Можно добавить onUnload к дескриптору <body> следующим образом: <body onLoad="checkBrowser()" onUnload="clean()"> Затем определяется метод clean(): // обработчик событий onUnload function clean () { Листинг 14.3. Исходный код для LoadUnload.htm. noticeWindow.close(); :i noticeWindow — глобальная переменная, которая объявляется в дескрипторе <head> документа и ссыла- ссылается на окно Upgrade Notice, отображенное с помощью обработчика onLoad. Окно Upgrade Notice закрывается, когда пользователь покидает текущую страницу. Листинг 14.3 показывает полный исходный код для onLoad и onUnload. Обработка ошибок (onError) Объекты окна и изображения имеют обработчик собы- событий onError, который позволяет отслеживать ошибки, возникающие в процессе загрузки документа или изоб- изображения. Отслеженная ошибка будет либо синтаксичес- синтаксической ошибкой JavaScript, либо ошибкой времени выпол- выполнения программы, но не ошибкой браузера (типа сообщения сервера о том, что страница не существует). Глава 33 дает полное представление об отслеживании ошибок с помощью onError. Обработчик событий onError поддерживается в JavaScript 1.1 и последующих версиях. <html> <head> <title>Load/Unload Example</title> <scrlpt language="JavaScript"> var noticeWindow //Обработчик событий onLoad function checkBrowser (> { if t (navigator. appName = 'Netscape1) SS (navigator. appVersion = '4.0 (Win95; I)')) { noticeWindow = window . open <"", "NoticeWindow", "toolbar=0,width=300,height=100,resizable=0"> ; noticeWindow.document.write { "<HEADXTITLE>OpgradeNotice</TITbEX/HEMD>" ) ; noticeWindow. document, write ("<CENTERXBIGXB>Your Web Browser needs to be updated. Please your supervisor before noon. ^</BX/BIGX/CENTER>)' ) // Обработчик событий onUnload function clean {) { if ( noticeWindow != null ) { noticeWindow. close () }; I // ~> </script> </head> <body cnLoad="checkBrowser()" onUnload="clean(>"> <font color="#008000"> <centerXbigXb>Intranet Home Page</bX/bigX/center> < /body> </html>
Использование DOM Часть III Я Прерывание загрузки изображения (onAbort) В зависимости от размеров HTML-изображения, загруз- загрузка его может занимать много времени. В результате пользователи могут потерять терпение и остановить заг- загрузку изображения до ее завершения. Например, пользо- пользователь может прервать процесс загрузки, щелкнув на ссылке на другую страницу или нажав кнопку "Stop" в меню браузера. Объект Image и обработчик событий onAbort поддер- поддерживаются в JavaScript 1.1 и последующих версиях. Однако, если пользователь будет работать с частич- частично недогруженным HTML-файлом, может не произой- произойти что-то из задуманного разработчиком, и, вероятно, возникнут некоторые нарушения выполнения кодов для изображений сценария. Обработчик событий onAbort позволяет реагировать на прерывание загрузки изобра- изображения и вызывает в качестве ответа JavaScript-функцию. Например, предположим, необходимо предупредить пользователя о том, что HTML-документ не был загру- загружен полностью. Тогда к дескриптору <img> добавляют следующий обработчик событий: <img name="mapworld" SRC="global.gif'" onAbort="alert('You have not downloaded the "¦¦entire document. ') "> Замена обработчиков событий В JavaScript 1.1 и последующих версиях можно заменять обработчик события, назначенный в определении HTML-дескриптора. Например, в приведенном ниже листинге функция optionA() назначена в определении <input> в качестве обработчика события для объекта buttonl. Однако, второй сценарий вычисляет перемен- переменную choice. Если значение choice не равно "А", то, как видно из листинга 14.4, код заменяет назначенный об- обработчик событий на функцию optionBQ. Листинг 14.4 Пример замены обработчиков событий. <script language="JavaScript"> var choice = "A"; function optionA() { I function optionB() { </script> <body> <form name="forml"> <input type="button" name="buttonl" onClick="optionA()"> </form> <script language="JavaScript"> if (choice != "A") { document.forml.buttonl.onclick=optionB </script> </body> Обратите внимание, что обработчики событий — это ссылки на функции, поэтому при определении в коде не нужно добавлять к ним круглые скобки. Если бы код был определен так, как показано ниже, функция optionB() была бы вызвана, но не назначена в качестве обработ- обработчика событий: document.forml.buttonl.onclick=optionB () Программная генерация событий До сих пор в данной главе обсуждался ответ на события, сгенерированные пользователем (например, событие click) или системой (например, событие onllnload). В большинстве случаев код проектируется так, чтобы от- отвечать на эти события, как только они происходят. Од- Однако, разработчики JavaScript не должны рассчитывать только на внешние факторы, генерирующие события. В действительности, можно вызывать возникновение не- некоторых из этих событий внутри кода. Например, можно смоделировать событие click для объекта Button, вызывая его метод click(). Хотя это вер- верно для объекта Button, но, например, для объекта Link (у которого имеется обработчик событий onClick) метод click() не существует. События таймера Множество управляемых событиями сред программиро- программирования используют событие таймера, которое является событием, вызываемым каждый раз по прошествии за- заданного интервала времени. Хотя JavaScript не предла- предлагает событие типа таймера, для тех же целей можно ис- использовать метод setlnterval объекта Window. ' ' ~~' ПРИМЕЧАНИЕ Метод setlnterval поддерживается в JavaScript 1.2 и последующих версиях. Метод setlnterval многократно вызывает функцию или вычисляет выражение каждый раз по истечении указанного интервала времени (в миллисекундах). Этот метод будет выполняться, пока окно не закроется или пока не будет вызван метод clearlnterval.
Управление событиями Например, в листинге 14.5 метод setlnterval выпол- выполняется, когда документ открывается и начинает вызы- вызывать функцию dailyTaskO каждые 10000 миллисекунд. Функция dailyTaskO ПРИ каждом вызове проверяет время, и в 8:30 утра начинает выполняться код в опе- операторе if, предназначенный для подачи сигнала пользо- пользователю и очистки интервала. Как только вызывается метод clearlnterval, выполнение setlnterval останавлива- останавливается. Листинг 14.5. Исходный код для Timer12.htm. <head> <script language="JavaScript"> function dailyTaskO { var tdy = new Date () ; if ((tdy.getHoursO = 8) && (tdy.getMinutesO = 30)) { alert('Good morning sunshine! ') clearlnterval(timerlD) \ II—> timerlD = setlnterval ('dailyTask()', 10000) </script> </head> При использовании JavaScript 1.1 или более ранней версии можно выполнять подобный процесс (хоть и не таким прямым способом) с помощью методов setTimeout() и clearTimeout(). Обычно метод setTimeoiit() используется для вычис- вычисления выражения по прошествии определенного проме- промежутка времени. Это вычисление — одноразовый процесс, который не повторяется бесчисленное количество раз. Однако, поскольку в JavaScript есть возможность произ- производить рекурсивные вызовы функции, рекурсию можно использовать для создания события таймера де-факто. Предположим, что каждое утро в 8:30 необходимо выполнить задачу, описанную немного выше. Для этого нужно иметь таймер, вычисляющий время; когда это время достигнуто, процесс запускается. Метод dailyTaskO определяется так: function dailyTaskO { var tdy = new Date () ; if ((tdy.getHoursO = 8) && (tdy.getMinutesO =30)) { performProcess()} timerlD = setTimeout("dailyTask()",10000) Метод создает объект Date, содержащий текущее время, с помощью getHours() и getMinutes(). Если они вычисляют 8:30 утра, вызывается метод performProcess(). Глава 14 Следующая строка — основа процесса таймера — ис- использует метод seffimeoutO для рекурсивного вызова ме- метода dailyTaskO каждые 10000 миллисекунд. Этот пример демонстрирует определенные трюки в отношении таймера, и лучше быть поосторожнее с подобной реализацией процесса в реальных задачах. Осуществление такого непрерывного процесса выпол- выполнения цикла е браузере может привести, в конце концов, к нехватке ресурсов. Для запуска таймера при загрузке документа потре- потребуется добавить обработчик событий onLoad в дескрип- дескриптор <body> HTML-документа: <body onLoad ="dailyTask()"> Листинг 14.6 содержит полный исходный код приме- примера. Листинг 14.6. Исходный код для Timer11.htm. <head> <script language="JavaScript"> < ! — function performProcess() { alert ('Good morning sunshine! ') ; ) function dailyTaskO { var tdy = new Date (> ; if ((tdy.getHoursO = 8) && i (tdy.getMinutesO = 30)) { perf ormProcess () } timerlD = setTimeout("dailyTask()",10000) } II—> </script> </head> <body onLoad="dailyTaskО"> </body> Резюме Учитывая управляемый событиями характер JavaScript, можно утверждать, что твердое понимание встроенных событий — ключ к максимальному увеличению его мощ- мощности. В главе рассматривались события и связанные с ними обработчики событий. Особое внимание уделялось событиям, наиболее полезным для разработчиков, а так- также определенным примерам их использования. Эти ба- базовые знания понадобятся в следующих главах, в которых будут детально рассматриваться встроенные JavaScript- события.
Объект Window В ЭТОЙ ГЛАВЕ Объект Window Открытие и закрытие окон Навигация между окнами Отображение окон сообщений Работа с сообщениями строки состояния Объекты браузера Navigator — это объекты самого высокого уровня в иерархии JavaScript-объектов. Эти объекты не имеют дело с HTML; они имеют дело преж- прежде всего с браузером, например, с открытием новых окон браузера, перемещением по списку посещений или по- получением имени хоста из текущего URL. В этой главе подробно рассматривается объект Window (который, как было сказано, находится на вершине объектной иерар- иерархии), а также упоминается группа других объектов, хотя детальное объяснение им будет дано в следующих гла- главах. Эта группа включает в себя объект Frame, который будет обсуждаться в главе 18. Кроме того, рассматрива- рассматриваются объекты Location, History и объект Navigator уров- уровня приложения. Объект Window Объект Window верхнего уровня, который является ро- родителем других дочерних объектов, присутствует на каж- каждой Web-странице, и, безусловно, в одном JavaScript- приложении их можно иметь несколько. Основные Таблица 15.1. Основные методы объекта Window. методы объекта Window реализуют вполне очевидные функциональные возможности (см. табл. 15.1): Как было показано в главе 9, Window — объект вер- верхнего уровня в иерархии объектов JavaScript. В отличие от других объектов, которые могут присутствовать или отсутствовать в среде выполнения, объект Window все- всегда присутствует — либо в мультифреймовом окне, либо в одиночном. Однако, отличие объекта Window от дру- других заключается в том, что его часто можно просто иг- игнорировать. Вот две причины этого. Первая причина: при работе в среде одиночного фрейма можно игнорировать явную ссылку на объект Window. JavaScript выводит ссылку в текущее окно. На- Например, следующие два кода эквивалентны и выдают ¦один и тот же результат: myTitle myTitle window.document.title document.title Вторая причина: в силу особой структуры языка JavaScript, некоторые методы системного уровня (напри- (например, всплывающие окна сообщений или установка тай- таймера) присвоены объекту Window. Метод Описание Open и Close Открытые и закрытие окна браузера; есть возможность определять размер окна, его содержимое, а также наличие кнопочной панели, поля адреса и других атрибутов. Alert Появление окна сигнального диалога с соответствующим сообщением. Confirm Появление окна диалога подтверждения с кнопками "ОК" и "Cancel". Prompt Появление окна диалога подсказки с полем текстового ввода. Blur и Focus Удаление или установка фокуса на окно. ScrollTo Прокрутка содержимого окна до определенной точки. Setlnterval Установка временного интервала между функциональным вызовом и вычислением выражения. SetTimeout Установка однократного временного интервала до функционального вызова или вычисления выражения.
Объект Window Однако, для вызова этих методов нет необходимос- необходимости использовать ссылку непосредственно на окно; такая ссылка будет неявной. Работа с объектами Window — сложная часть про- программирования на JavaScript из-за способов, по которым пользователи применяют окна браузера. Хотя большин- большинство пользователей обычно имеют дело только с одним окном, иногда бывает полезно открыть сразу два и боль- больше окон. Так можно сравнивать страницы различных сайтов, вводить информацию в форму, используя дан- данные с другой Web-страницы, а также проводить поиск элементов списка одной страницы, просматривая ссыл- ссылки с помощью еще одного экземпляра браузера. Термин окно браузера часто сокращается до просто- окна, хотя нужно быть внимательнее и не путать разные копии браузера с фреймами, которые также называют окнами (подокнами окна браузера). Окно браузера так- также называют верхним (top) окном, потому что фреймы — это подокна браузера. Браузеры, поддерживающие JavaScript, позволяют программно открывать и закры- закрывать окна браузера, а также перемещаться по этим ок- окнам. Сайт с отдельными окнами сможет обеспечить сразу несколько версий содержимого, увеличив тем са- самым доступ к информации и возможностям и предло- предложить новые пути более полного взаимодействия с сай- сайтом. ''¦^ПРИМЕЧАНИЕ "' ''! " 1Р^1Щ*3??, В JavaScript 1.2 в Window было добавлено несколько новых методов: atob, back, btoa, captureEvents, clearlnterval, crypto.random, crypto.signText, disableExternalCapture, enableExternalCapture, find, forward, handleEvent, home, moveBy, moveTo, releaseEvents, resizeBy, resizeTo, routeEvent, scrollBy, scrollTo, setHotKeys, setlnterval, setResizable и setZOptions. Кроме того, добавилось несколько новых свойств: crypto, innerHeight, innerWidth, locationbar, menubar, offscreenBuffering, outerHeight, outerWidfh, pageXOffset, pageYOffset, personalbar, screenX, screenY, scrollbars, statusbar и toolbar. Для JavaScript 1.2 требуется Navigator 4.0-4.05, в то время как для JavaScript 1.3 — Navigator 4.06-4.5. Во многих случаях для одновременного просмотра страниц удобнее использовать фреймы (см. главу 18). Однако, у пользователей есть возможность изменять размеры и положение множества отдельных окон брау- браузера. Пользователи могут также сворачивать и разворачи- разворачивать окно, при необходимости перемещать окно поверх или вниз всех окон и сохранять все инструментальные средства и другие особенности (строку меню, поле ад- адреса, строку состояния, закладки и т.д.) в каждом эк- экземпляре браузера. Глава 15 Многие пользователи считают отвлекающим и раздра- раздражающим неожиданное открытие новых окон браузе- браузера, в особенности, если они потом должны сами зак- закрывать их. Уведомьте посетителя о том, что данное действие откроет новое окно — например, с помо- помощью короткого примечания рядом со ссылкой. В сле- следующем примере Spike — это ссылка, которая откры- открывает новое окно: See a picture of my dog spike, (new window) Открытие и закрытие окон f ПРИМЕЧАНИЕ * "'¦' Пользователь в любой момент может открыть новое окно, выбрав File, New Browser (или что-то подобное). Однако, сослаться на такое окно из JavaScript не уда- удастся. При помощи JavaScript можно открывать и закрывать окна браузера. Разработчик может создать новое окно с определенным документом, загружающимся в него при выполнении некоторых условий. Можно также указать,, например, размер нового окна и параметры, доступные в окне, а также присвоить окну имя (для ссылок на него). Хотя открытие окна подобно созданию нового объекта Window, в данном случае конструктор new не использу- используется. Вместо этого применяется следующий синтаксис: WindowVar = window, open (URL, windowName, [ , windowFeatures]) Параметры метода ореп(): URL. URL целевого окна. Этот параметр не обяза- обязателен. Если URL — пустая строка (""), браузер от- открывает пустое окно, позволяя использовать метод write() для создания динамического HTML. windowName. Имя объекта Window. Имя также не обя- обязательно; однако для обращения к окну с помощью ссылок или форм имя необходимо. Можно присво- присвоить имя позже, через свойство window.name. • windowFeatures. Список атрибутов отображения для окна браузера. Если окно открылось, метод ореп() возвращает мет- метку объекту Window. Если окно почему-либо не было открыто, данный метод возвращает значение Null. ^ПРИМЕЧАНИЕМ Два имени, относящихся кокну, функционально — не одно и то же. Рассмотрим следующий код: myWindow=window.open ("" , "newWindow") ; myWindow — переменная объекта, который открыл newWindow. newWindow — имя нового окна. На свойства нового окна можно ссылаться с помощью! переменной myWindow. Ссылки и формы могут об-
Использование DOM Часть III ращаться к новому окну с использованием его имени new Window. Ссылки на окна При работе с одиночными и множественными фрейма- фреймами в JavaScript-приложениях, возможно, потребуется использовать и другие способы ссылок на окна. JavaScript обеспечивает четыре вида ссылок на окна, и каждый из них реализуется как свойство объекта Window. Более подробная информация относительно ссылок на окна и фреймы будет дана в главе 18. Отдельные окна браузера не имеют иерархической структуры; однако, окно, содержащее код, который открывает другое окно, часто называется родительс- родительским окном. Соответственно, новое окно называется до- дочерним. Любое новое окно можно присвоить перемен- переменной из других окон так, чтобы другие окна могли ссылаться на нее и ее свойства. Для ссылки на свойство в новом окне используйте windowName.property. Рассмотрим следующий код; newWindow = window.open О; newWindow. location.href = "http://www.mcp.com/"," Хотя этот фрагмент — не самый эффективный спо- способ записи кода, он демонстрирует способ ссылки на свойство дочернего окна. Новое окно открывается и получает имя (в данном случае, newWindow). Затем устанавливается location.href нового окна. Текущее окно В главе 9 обсуждалось использование окон для ссылок на текущее окно. Однако, не было упомянуто, что объект Window содержит свойство под названием window, кото- которое может использоваться как инструмент ссылки на самого себя. Кроме того, свойство self объекта Window —- еще одно средство сделать окно текущим или активным. Например, следующие две строки кода — функциональ- функционально идентичны: window, defaultstatus = "Welcome to the Goat ^Farm Home Page" self. defaultStatus = "Welcome to the Goat Farm '•Home Page" Поскольку window и self— синонимы текущего окна, может показаться странным, что оба они включены в язык JavaScript. Как показано в предыдущем примере, это объясняется необходимостью увеличения гибкости, т.е., по желанию, возможно использовать либо window, либо self. Однако, насколько полезными могут быть window и self, настолько же они могут стать запутанными, если подойти к этому логически. В конце концов, свойство объекта, которое используется как эквивалентный тер- термин для самого объекта, довольно необычно. Следова- Следовательно, window и self будет удобнее считать зарезерви- зарезервированными словами для объекта Window, а не его свой- свойствами. Поскольку window и self— свойства объекта Window, нельзя использовать и window, и self в одном и том же контексте. Например, следующий код не будет работать: window.self.document.write("<hl>Test.</hl>") Наконец, в мультифреймовых средах window и self всегда относятся к окну, в котором выполняется JavaScript- код. В некоторых объектно-ориентированных или основан- основанных на объектах языках self может относиться к ак- активному объекту, независимо от его типа. В JavaScript self относится только к активным объектам Window или Frame — и ни к чему больше. Определение содержимого окна Параметр URL определяет, какое содержимое появится в новом окне. Если задается какое-то значение, браузер пытается найти и отобразить указанный документ: NewWindow = window.open("http:// www.acadians.com", "AcadiaPage", LO:WRONG) С другой стороны, можно отобразить пустую стра- страницу, указав в качестве параметра URL пустую строку (""). Используйте эту методику при необходимости ди- динамического создания HTML-страницы с использова- использованием JavaScript: newWindow = window.open(""r "DynamicPage" "") newWindow. document. wri te ("<Hl>Document created fusing JavaScript.</Hl>") newWindow.document.close() В главе 16 подробно рассматривается использование метода write() объекта Document для создания динами- динамического HTML. Определение атрибутов окна Параметр windowFeatures необходим при отображении окна, т.к. с его помощью настраивается внешний вид открытого окна. Параметр windowFeatures не обязателен; если он не используется, отобразится окно с такими же атрибутами, как у текущего окна. Таблица 15.2 содержит список атрибутов внешнего вида окна. ПРИМЕЧАНИЕ """ *"" Атрибуты alwaysRaised и z-lock, добавленные в JavaScript 1 .2, работают только на платформах Windows и Macintosh.
Таблица Атрибут 15.2 . Атрибуты метода ореп() для отображения Описание окна. иьъект Window PSai Глава 15 ЁШ width Ширина клиентской области Navigator в пикселах. См. innerWidth, который появился в JavaScript 1.2. height Высота клиентской области Navigator в пикселах. См. innerHeight, который появился в JavaScript 1.2. dependent Если значение равно yes, создает дочернее окно из текущего окна; в Windows дочернее окно в панели задач не появляется. Дочернее окно закрывается одновременно со своим родительским окном. Появился в JavaScript 1.2. toolbar Отображает/скрывает инструментальную панель браузера. menubar Отображает/скрывает меню браузера. scrollbars Отображает/скрывает горизонтальную и вертикальную полосы прокрутки браузера. innerWidth Определяет ширину области содержания окна. Окна размером меньше, чем 100x100 пикселов, требуют подписанного сценария. Атрибут появился в JavaScript 1.2. Заменяет width, который также может использоваться для совместимости сверху вниз. innerHeight Определяет высоту области содержания окна. Окна размером меньше, чем 100x100 пикселов, требуют подписанного сценария. Атрибут представлен JavaScript 1.2. Заменяет height, который также может использоваться для совместимости сверху вниз. resizable Разрешает/запрещает изменение размеров окна браузера. screenX Определяет расстояние от левой стороны экрана до нового окна. Окно может быть помещено за пределами экрана с помощью атрибута в подписанных сценариях. Появился в JavaScript 1.2. screenY Определяет расстояние от вершины экрана до нового окна. Окно может быть помещено за пределами экрана с помощью этого атрибута в подписанных сценариях. Появился в JavaScript 1.2. status Отображает/скрывает строку состояния браузера, location Отображает/скрывает окно URL-адреса. directo'ies Если значение равно yes, отображает вторичную инструментальную панель (Netscape) с кнопками наподобие "What's New" и "What's Cool". copyhistory Копирует список посещений текущего окна в новое окно. outerWidth Ширина окна Navigator в пикселах (JavaScript 1.2). outerHeight Высота окна в пикселах (JavaScript 1.2). left Расстояние в пикселах от левой стороны экрана (JavaScript 1.2). top Расстояние в пикселах от верха экрана (JavaScript 1.2). alwaysLowered Создает окно браузера, которое всегда помещается ниже других окон, независимо от того, является ли оно активным (появился в JavaScript 1.2). Безопасная возможность, требующая подписанного сценария. alwaysRaised Если значение равно yes, создает окно браузера, которое помещается выше других окон, независимо оттого, является ли оно активным. Появился в JavaScript 1.2. Безопасная возможность, требующая подписанного сценария. z-lock Создает новое окно браузера, которое не всплывает поверх других окон при помещении в фокус (JavaScript 1.2). Атрибуты height и width Определяют размеры окна в. пикселах и совместимы сверху вниз с JavaScript 1.0 и 1.1, хотя предпочтительнее использовать вместо них соответ- соответствующие ключевые слова — innerWidth и innerHeight. Остальные атрибуты устанавливаются с помощью логи- логических значений: значение true — 1, yes или атрибут alone; значение false — 0, по или отсутствие атрибута вообще. Например, если необходимо отобразить новое окно только с инструментальной панелью и меню, ис- используют следующий синтаксис: NewWindow = window.open (LO:WRONG, "myWindow", "toolbar=l, menubar=l") Следующий синтаксис также допустим: NewWindow = window, open ("", "myWindow", "toolbar=yes, menubar=yes") NewWindow = window.open (" " , "myWindow", "toolbar, menubar") Таким образом, можно просто не учитывать те ат- атрибуты, которые не определены. Эти атрибуты имеют значения false. .ПРИМЕЧАНИЕ '_"'"' ' " ¦ .Ъ: ' ' Атрибуты outerWidth, outerHeight, left и top, добавлен- добавленные в JavaScript 1.2, обеспечивают абсолютное пози-
Использование DOM Часть III ционирование окон браузера на рабочем столе. InnerWidth и innerHeight обеспечивают контроль над точными размерами окон браузера, хотя при исполь- использовании JavaScript 1.0 или 1.1 вместо них необходи- необходимо применять ключевые слова width и height. , совет -, , «., „. ,,.Л>ь ,.„,„ Ошибка в некоторых версиях браузера Netscape Navigator не позволяет использовать метод window.ореп() для ¦отображения документов. Для обхода этой ошибки нужно повторить команду открытия окна: myWindow = window, open ("new.html" , "newwindow") ; myWindow = window.open("new.html", "newwindow"); При таком повторении newWindow и его документ ото- отобразится во всех версиях браузеров Netscape Navigator. ^ Примечание Ci; В дополнение к методу window.openl), для открытия нового окна можно также применять атрибут ссылки TARGET = "_blank" или даже целевой атрибут со значением любого имени (окна или фрейма), не ис- используемого в данный момент. Ссылка <HREF = "foo.html" TARGET = "bar">foo</A> открывает окно браузера, именует заголовок окна и загружает в окно документ foo.html, пока одно из текущих окон или фреймов не получит имя bar (имена окон и фрей- фреймов зависят от регистра). Кроме того, ссылка TARGET = "_blank" создает не- непоименованное окно, которое в дальнейшем тяжело поддается модификациям. С помощью _blank ссыл- ссылка (та же самая ссылка или другая) просто создает еще одно новое окно вместо обновления открытого ранее. ^ Закрытие окон Для закрытия окна используют метод close() объекта Window. Если требуется закрыть текущее окно, вызов метода будет выглядеть просто как window.close(). В от- отличие от других методов объекта Window, таких как alert() или SetTimer(), метод close() должен всегда сопро- сопровождаться объектной ссылкой. Если метод closeO ис- использовать без объектной ссылки, может закрыться те-' , кущий документ, а не окно, в зависимости от контекста вызова метода. Причина в том, что объект Document также имеет метод close(). Таблица 15.3 содержит не- некоторые типичные коды сценария, в которых можно применять метод close(). ©ПРИМЕЧАНИЕ , „* Более поздние версии Netscape не допускают, чтобы метод window.closel) закрывал окна, которые были созданы не JavaScript. Эта мера защиты не позволя- позволяет шутникам вставлять нежелательный код в гостевые книги и т.п. Данная мера не затрагивает любое закон- законное использование метода window.closet). Функция или обработчик событий с window.close() закрывают окно, содержащее их: <PORM> <INPOT* TYPE="BUTTON" VRLUE="Close Window" onClick="top.close 0"> </FORM> Для обработчика событий типа onClick необходимо определять имя окна, например, window, parent, top, self либо имя установленной переменной, например, myWindow, как в window.closel) или в myWindow.closel). Простое использование closet] в обработчике собы- событий подразумевает document, closel). Можно закрывать окно с помощью ссылки на то же самое окно, из которого данное окно было открыто, используя переменную, установленную равной новому окну: myWindow = window.open("new.html", "newwindow"); <FORM> <INPOT TYPE="BUTTON" VftLUE="Close Window" onClick="myWindow. close {)" > </FORM> 1ПРИМЕЧАНИЕ -w, newWindow.closel); работать не будет. Имя newWindow можно использовать в предыдущем примере для иден- идентификации окна (свойство window.name) и для адре- адресации окна в ссылках и формах. Однако, нельзя ис- использовать newWindow для ссылки на новое окно и его> свойства. Таблица 15.3. Метод closeQ и открывающие окна. Close 0/Opener Описание window.opener.close() document.write("<br>opener property is " + window.opener.name) top.opener.closeQ window.opener.docurnent.bgColor='bisque' window.opener=null > Закрывает окно, из которого было открыто текущее окно. Определяет имя окна, из которого было открыто текущее окно. Закрывает главное окно браузера. Изменяет цвет фона окна, определенного свойством opener. Устанавливает значение свойства opener равным Null, предотвращая закрытие открывающего окна.
Объект Windm Глава 15 При использовании метода window.closel) хорошо было бы обеспечить кнопку или ссылку для пользователей, чтобы они могли закрыть новое окно по завершении работы с ним. (Некоторые пользователи, в особенно- особенности новички, могут не знать, как закрыть окно, или могут по ошибке выйти из браузера вместо закрытия окна.) Можно использовать условный оператор для со- создания закрывающей кнопки или ссылки, если доку- документ загружен в названном явно окне (новое окно): <SCRIPT IANUAGE="JavaScript"> <! — .//newWindow is the name given the new window if(top.name == "newWindow" { document.write) '<A HREF="javascript: + ' this window to return to previous window.") ; } // Для наглядности угловые скобки не // представляются своими ходами: // unescape("%3C"), unescape("%ЗЕ"). //Однако в реальных кодах » о потребуется //делать, чтобы они не воспринимались как //дескрипторы комментария в старых браузерах. </SCRIPT> Форма на рис. [5.1 демонстрирует различные аспек- аспекты открытия и закрытия окон. Заполняя форму, можно по желанию определить просмотр нового окна. Листинг 15.1. OpenWindow.htm. Window Open Example Р/еязо select motoitowingtlbptayoptions «ntf tftwt click If» Open Wlmtowtortton. WggisJyou like an easting page or one treated on the ty? " &tsnng Page | r Dynamic Раве Window Attributes: Г Tbolbec Г Iftnubtr Г Status. Г Location Г cu^tun fite Vldch: I Height: f Г Directories Г Сор/- Hif4.DC.;' — iininrviiBiirti шгшатшей В первом поле определяют параметр URL — исполь- используя существующий URL или создавая страницу "на лету". Второе поле позволяет определять каждый из до- доступных атрибутов окна. По умолчанию все поля не заполнены. Можно заполнить требуемые из них. За счет заполнения полей "Custom Size" можно определить раз- размеры нового окна. При нажатии кнопки "Open Window" всплывает но- новое окно, показанное на рис. 15.2. Листинг 15.1 содержит исходный код этого примера. <html> <head> <title>Window Open</title> <SCRIPT IANGUAGE="JavaScript"> << — var newWindow .// Открыть окно на основе атрибутов, определенные пользователем function openWindow() { // Построение списка параметров windowFeatures var winAtts = ' if {document.winOptions.toolbarOption.checked) { winAtts += "toolbar=l," } i f (document.winOptions.menubarOption.checked) { winAtts += " ienubar=l," ) if (document.winOptions.scrollbarsOption.checked) { winAtts += "scrollbars=l," ) if (document.winOptions.resizableOption.checked) { winAtts += "resizable=l," ) if (document.winOptions.statusOption.checked) { winAtts += "status=l," } if (document.winOptions.locationOption. checked) { winAtts += "location=l," } if (document.winOptions.directoriesOption.checked) ( winAtts += "directories=l," ) if (document.winOptions.copyHistoryOption.checked) ( winAtts += "copyhistory=l," ) if (document. winOptions. customSizeOption. checked) ( winAtts += "height=" + document.winOptions .heightBox. value winAtts += "width=" + document. winOptions. widthBox. value + I winAtts = winAtts. substring @, winAtts . length-2) // Определить URL и отобразип окно
Использование DOM ЧастьШ if (document.winOptions.pageType[l] .checked) { var urlVar = "" urlVar = document. winOptions . urlBox. value newWindovf = window, open (urlVar, "newWindow" ,winAtts) ) else { newWindow = window, open (""/'newWindow" ,winAtts) newWindow. document, write ("<Hl>WindowOpen Test</HlXp>") // Закрыть OKRO function closeWindow ( ) { newWindow. close ( > I // ~> </SCRIPT> </head> <body background=" . ./lt_rock.gif"> <hlxfont color="#008040">Window Open Example</fontX/hl> <pXiXb>Please select the following display options and then click the Open Window button. </iX/BX/p> <form name="winOptions" method="POST"> <p>Would you like an existing page or one created on the fly?</p> <input type=radio checked name="pageType" value="existing">Existing Page ¦< input type=text size=30 maxlength=25 6 name= " urlBox " x/p> < input type=radio name="pageType" value="dynamic">Dynamic Page</p> <hr> <p>Window Attributes :</p> <preXinput type=checkbox name—"toolbarOption" value="ON" >Toolbar <input type=checkbox name=t'menubarOption" value="ON">Menubar <input type=checkbox name="scrollbarsOption" value="ON">Scrollbars <input type—checkbox name="resizableOption" value="ON">Resizable</pre> <preXinput type=checkbox name="statusOption" value="ON">Status <input type=checkbox name="locationOption" value="ON">Location <input type=checkbox naine= " directoriesOption " value="ON">Directories <input type=checkbox name="copyHistoryOption" value="ON">Copy History</pre> <preXinput type=checkbox name="customSizeOption" value="ON">Custom Size</pre>
Объект Window Глава 15 <pre>Width: < input type=text size=5 maxlength=5 name="widthBox"> Height: <input type=text size=5 maxlength=5 name="heightBox"> type="button" name= " OpenButton" value="Open Window" onClick="openWindow(> "> <input type="button" nane="CloseButton" value="Close Window" onClick="doseWindow(> "X/pre> </form> <p>finbsp;</p> </body> </html> <input Window Open Test f j Ш xample (У options and Шел eltcKthe Open Windowbutton. ?ne created on the* Window Attributes: Г Toolbar Г mm T Bta Г (.dsi IP" Custom 5k; ¦ - РИСУНОК 15.2. Отображение нового окна. Навигация между окнами Возможно, что в течение одного сеанса пользователь от- откроет большое количество окон; однако, в каждый мо- момент вргме! ; только одно окно из них может быть ак- активным, т.е. быть в фокусе. Наличие фокуса означает, что окно может непосредственно получать вводимые данные и отвечать на ввод пользователя. Кроме того, окно в фокусе — обычно самое верхнее окно на дисп- дисплее, т.е. окно в активном режиме накладывается на дру- другие окна. (В UNIX и X Window окно в фокусе бывает и на заднем плане.) Пользователь может передвигаться между окнами с помощью мыши. Обычно щелчок на окне переводит на это окно фокус. В некоторых версиях UNIX для пере- перевода окна в фокус достаточно перемещения курсора мыши поверх окна; напротив, вывод курсора за преде- пределы окна выводит и фокус (или деактивирует) из окна. Перекладывание действий на пользователя — не единственный путь, а иногда — и не лучший путь пе- передачи окну фокуса. JavaScript и HTML обеспечива- обеспечивают несколько методов для установки и удаления фокуса автоматически — с использованием кода. Эти автома- автоматические установки и удаления фокуса позволяют пе- перемещаться по окнам с минимальным участием пользо- пользователя или вообще без оного. Вместо генерации сооб- сообщения для пользователя, приглашающего щелкнуть на окне, код может автоматически передавать фокус окну. Это не означает, что пользователь не будет управлять сеансом, однако он получит помощь, подобную автопи- автопилоту. Хотя многим сайтам не нужны многократные окна, сайтам, которые в них нуждаются, может оказаться удобно программно управлять этими окнами. JavaScript предоставляет хорошие средства управления окнами с помощью открывающих и закрывающих методов, опи- описанных выше, и с помощью методов установки и уда- удаления фокуса из окна. Все эти методы управления ок- окнами объединяются в программную систему навигации по окнам. В JavaScript простое определение объекта окна или его документа, или даже изменение свойства в окне, не переводит окно в фокус. Переводить окно в фокус мож- можно двумя способами: Косвенно, устанавливая в фокус один из объектов в окне. Непосредственно, устанавливая фокус на само окно. Косвенная установка фокуса Окно, открытое с помощью переменной п indow и содержащее документ с формой myF< и элементом ввода mylnpul может получить фокус через окно, из которого оно было открыто, с помощью такого кода:
Использование DOM Часть III myWindow.document.myForm.mylnput.focus(); Элемент ввода, mylnput, получает фокус, и в резуль- результате myWindow, который содержит mylnput, также по- получает фокус. Новое окно может передавать фокус окну, которое открыло его, с помощью своего свойства opener: window.opener.focus(); ПРИМЕЧАНИЙ -¦— '~--' - Свойство opener поддерживается в JavaScript 1.1 и следующих версиях. Для перевода фокуса из нового окна на окно, из ко- которого оно было открыто, в ранних версиях JavaScript- браузеров для нового окна требовалась переменная для ссылки на открывающее окно: myWindow = window.open("new.html", "newWindow"); myWindow. oldWindow = top; Новое окно может ссылаться на старое окно и кос- косвенно передавать ему фокус: oldWindow.Document.myForm.mylnput.focus() ; Прямая установка фокуса Окно может получить фокус непосредственно при ис- использовании метода window.focus(). Если окно ссылает- ссылается на другое окно с помощью переменной типа myWindow, оно передает фокус другому окну: myWindow.focus(); Новое окно может передавать фокус окну, которое открыло его, с помощью свойства opener: window.opener.focus(); Вызов функции в окне может передавать фокус окну, если функция содержит window.focus(): function focusDemo(){ top.focus; .... остальная часть функции I , Методы window.focusl) и window.blur|), как и свой- свойство opener, поддерживаются только в JavaScript 1.1 и следующих версиях. Для обеспечения согласования с ранними версиями браузера необходимо использо- использовать косвенную методику установки фокуса. Удаление фокуса Деактивизация окна (удаление из него фокуса) выпол- выполняется путем передачи фокуса другому окну. Посколь- Поскольку в каждый момент времени только одно окно может иметь фокус, передача фокуса окну непосредственно или косвенно деактивизирует другие окна. С помощью метода window.blur() из окна можно не- непосредственно удалить фокус без передачи фокуса дру- другому окну. Для window.blurQ можно использовать лю- любое из средств, применяемых с window.focus(). 'ПРИМЕЧАНИЕ ¦'",_. Согласно документации Netscape, щелчок на ссылке в окне передает этому окну фокус: <А. HREF="some.html" TARGET="myWindow">My Window</A> Щелчок на ссылке загрузит документ some.html в окно myWindow и передаст фокус myWindow. Если myWindow не существует, будет открыто новое окно, после чего в него загрузится some.html и новое окно получит фокус. Эта методика работает не во всех версиях браузеров. Иногда, если окно уже открыто, оно может и не по- получить фокус. Отображение окон сообщений Диалоговые окна — традиционно важная часть при- прикладной программной среды. Пользователям Windows известно, что диалоговые окна присутствуют как в дан- данном, так и в других графических пользовательских ин- интерфейсах. JavaScript может отображать стандартные диалоговые окна для уведомлений пользователя или получения информации перед продолжением работы. Однако, из-за немодального характера Web использовать диалоговые окна не рекомендуется. Обычно лучше свя- связываться с пользователем другим способом. Модальные диалоговые окна достаточно обычны в при- прикладных программах Windows. Если вы пришли из мира Windows 4GL, убедитесь, что вы подкорректировали свое мнение относительно их использования. Язык JavaScript не так строго понимает это замеча- замечание, добавляя префикс к отображаемым сообщениям. Для сигнальных сообщений, перед сообщением появ- появляется "JavaScript Alert". Для диалоговых окон подтвер- подтверждения — "JavaScript Confirm", а в диалоговых окнах подсказки появляется "JavaScript Prompt". В результате пользователь может легко определить источник появив- появившегося диалогового окна. 1|ПРИМЕЧАНИЕ Помимо возможности обеспечения самого сообщения, не существует возможности настраивать просмотр окон сообщений JavaScript. Заголовок и пиктограммы — всегда одни и те же. Простое уведомление Для передачи пользователю информации используется метод alert() объекта WindowQ. Сигнальное диалоговое
Объект Window окно отображает сообщение с одной кнопкой "ОК.", зак- закрывающей данное окно. Это модальное диалоговое окно, поэтому пользователь будет вынужден закрыть его перед продолжением работы в браузере (даже в муль- •ифреймовых документах). При закрытии диалогового окна никакие значения не возвращаются. Его синтаксис таков: [window. ] alert {.message) Можно отображать информацию относительно теку- текущего окна в сигнальном сообщении с помощью кода, показанного в листинге 15.2. Листинг 15.2 DisplavWindowlnfo.htm. <нтщ> <HEAD NAME = "WindowPane"> <SCRIFT LANGUAGE = " JavaScript"> function displayWindowInfo() { var winlnfo = ' winlnfo = "Number of frames: ' + window.length + "\r" winlnfo += "Window object name: + window.window + "\r" winlnfo += "Window parent name: ' + window. parent + "\r" winlnfo += "URL: " + window. location alert(winlnfo) 1 </SCRIPT> </HEAD> <BODY> <FORM> <INPUT „\r" </INPOT> </FORM> </BODY> Type="button" Value="Display Window Information" OnClick="displayWindowInfo()" На рис. 15.3 показано сигнальное диалоговое окно, которое отображается при нажатии кнопки. Параметр message метода alert() — обычно строка, хотя это не обязательное требование. Поскольку JavaScript не является строго типизированным языком, можно отображать информацию других типов данных без пре- преобразования данных в строку. В качестве параметра можно использовать даже объект, как показано в лис- листинге 15.3. На рис. 15.4 представлен результат. Листинг 15.3. DisplayWindowObjectlnfo.htm. <HTML> <HEAD> <SCRIPT LANGUAGE = "JavaScript"> function Application(Title, ProgramName, Path, Vendor) { this.Title = Title this. ProgramName = ProgramName Глава 15 this.Path = Path this.Vendor = Vendor ) function displayApp () { alert(Application) </SCRIPT> </HEAD> <BODY> <H1X/H1> <FORM> <INPUT Type="button" Value="Display Obj ect Definition" OnClick="displayApp()" </INPUT> </FOPM> </BODY> РИСУНОК 15.3. Сигнальное диалоговое окно. РИСУНОК 15.4 Определение объекта, отображенное в сигнальном диалоговом окне.
Использование DOM Часть Yes/No-подтверждение В дополнение к простому отображению информации в диалоговом окне, можно задавать пользователю вопрос, используя метод confirm() объекта Window. Диалоговое окно подтверждения отображает кнопки "ОК" и "Cancel", причем каждая из них возвращает значение. "ОК" воз- возвращает true, a "Cancel" — false. Как подразумевается в имени метода, обычно используют диалоговые окна под- подтверждения, чтобы пользователь подтвердил действие, которое собирается совершить. Синтаксис в данном слу- случае выглядит так: returnValue [window.]confirm(message) Обычное диалоговое окно подтверждения должно предлагать пользователю подтвердить отправку формы либо сообщения по электронной почте. Листинг 15.4 показывает, как можно использовать метод confirm() для возврата значения onSubmit обработчику событий фор- формы. Если пользователь щелкает на "ОК", форма отправ- отправляется по указанному адресу. Если же щелчок выполня- выполняется на кнопке "Cancel", событие не генерируется. Листинг 15.4. JavaScriptChronicles.htm. <html> <head> LeMJntitled Normal Page</title> <SCRIPT LANGUAGE="JavaScript"> if irmAction ( 5 { return < о you really want subscription?") </SCRIPT> </head> <body> t Chronicles — Free Subscription Form</emX/h2> <form action="mailto:subscribe@jschronicles.com" method="POST" name="SubscribeForm" onSubmit="return confirmAction()"> other magazines do you currently subscribe to? <prexinput type= >PC Week <input 1 value= 4 >DBMS < input type= value=" SKU07 " >Wired <input type >Yahoo < input type value="SKU02">InfoWorld < input 1 >Databased Advisor < input type=ch value="SKO08">Web Publisher <input type=checkbox name="Cl-SKUll" value="SKUll">Internet Advisor <input type=checkbox name="Cl-SKU03" value="SKU03">PC Magazine <input type=checkbox name="Cl-SKU06" value="SKU06">Delphi Informant <input type=checkbox name= value="Cl-SKU09">Web Informant <input type=checkbox name="Cl-SKO12" value="SKO12">JavaWorld </pre> </li> <li>Please enter the reason you would like to subscribe to <em> JavaScript Chronicles : </emXbr> <br> <textarea name="Comments" rows=6 cols=46> </textareaX/li> </oL> <p> <input type=submit name="Submit" value="Submit" > </form> </body> </html> На рис. 15.5 показано окно подтверждения, которое отображается при нажатии кнопки "Submit". Г Ybjibcj Г liLtSUoiMd Г ОАЕ-.Ьгчг 1 J.difi.ini- Г ГСеЬ P-ftiJ^s^pi Г JavnCct id Г:-""""- L' " ' "**""""¦ " ж Si бЕгйгй1.":.77-тк •"-¦¦ ¦-- .¦-¦:¦¦—- г 1 ^Ш РИСУНОК 15.5. Диалоговое окно подтверждения возвращает ответ пользователя. Пользовательский ввод Третье диалоговое окно, которое можно использовать для получения пользовательского ввода, вызывается с помощью метода Prompt() объекта Window. Воспользуй- Воспользуйтесь диалоговым окном подсказки, когда требуется по- получить значение от пользователя. Это диалоговое окно
Объект Window состоит из сообщения, поля пользовательского ввода и кнопок "ОК" и "Cancel". Метод Prompt() имеет следу- следующий синтаксис: returnValue = [window.]prompt(message, defaul tReply) Как видно из этого примера, в дополнение к указа- указанию сообщения диалогового окна необходимо опреде- определить параметр defaultReply. Это значение будет заданным по умолчанию текстом, вставляемым в поле пользова- пользовательского ввода окна. Данный параметр нужно опреде- определять даже в том случае, когда он не имеет никакого зна- значения по умолчанию. — ... ¦ . ПРИМЕЧАНИЕ Будьте уверены, что для диалогового окна подсказки определен заданный по умолчанию ответ. Если не добавлять этот параметр, JavaScript поместит в поле ввода Undefined, которое может запутать пользова- пользователей. Если значений по умолчанию нет, используйте для этого параметра пустую строку {' Если пользователь щелкает на "ОК", метод Prompt() возвращает значение строки, введенное пользователем. Если пользователь ничего не ввел, возвращается пустая строка (""). Однако, если он щелкнет на "Cancel", воз- возвращается значение Null. ПРЕДУПРЕЖДЕНИЕ •Не считайте, что пользователь будет всегда нажимать на "ОК" в диалоговом окне подсказки. Всякий раз при использовании метода Prompt!) необходимо гаранти- гарантировать, что непустое значение возвращается раньше чем оно будет использовано в вычислениях. В таком случае, если пользователь нажмет на "Cancel", про- программа будет работать со значением строки "null", а не с тем, что было фактически введено пользова- пользователем в поле текстового ввода. Листинг 15.5 показывает пример использования окна подсказки. Пользователю предлагают ввести текст в поле (см. рис. 15.6). Этот текст затем используется в новом окне, как показано на рис. 15.7. Листинг 15.5. UserTexthtm. <HTML> <H?AD> <SCRI?T LANGUAGE = " JavaScript"> function showBoxO { userText = prompt ("Enter the text i your " + "pe: i browser ' own browser text") if (userText null) { userWindow — window.open("", "userTextWindow", "toolbar=0") userWindow.document.write("<hl>" + userText + "</hl>") } ) </SCRIPT> <BODY> Глава 15 <FORM> <INPUT Type="button" Value="Create Your Own HTML Page" OnClick="showBox()" </INPOT> </FOKM> </BODY> Возвращаемое значение — это всегда строка. Если нужно обрабатывать его как другое значение, сначала его необходимо преобразовать. Например, если требуется вычислить общую стоимость на основе определяемой пользователем процентной ставки, можно получить ее значение с помощью метода Prompt(), как показано на рис. 15.8. Затем перед вычислением полной стоимости следует преобразовать это значение в вещественное чис- число при помощи метода parseEloat(). Листинг 15.6 пока- показывает код этого примера. Hl4..ll .jM.j.1... РИСУНОК 15.6. Диалоговое окно подсказки. Листинг 15.6. Calc.htm. <HTML> <HEAD> <SCRIPT LANGUAGE = "JavaS< function get { percent = p lat is the current -rate?", "8.5") if (percent != null) { e = p I * 20000 ) } </SCRIPT> <BODY> <FORM> <INPUT Type="button" :ulate Total Price" OnClick="getPercentageRate()" </INPUT> </FOEM> </BODY>
Использование DOM Часть III My own browser text РИСУНОК 15.7 Новое окно отображает содержимое, введенное пользователем. РИСУНОК 15.8 Полъзовательскийввод. Работа с сообщениями строки состояния Строка состояния браузера может оказаться важным средством взаимодействия с пользователем. Здесь можно задействовать два свойства объекта Window,, defaultStatus и status, для управления отображенным текстом. Вообще говоря, использовать строку состояния мож- можно двумя способами. Первый способ — отображать за- заданное по умолчанию сообщение в строке состояния. Пользователь видит это сообщение, не выполняя ника- никаких действий. Заданное по умолчанию сообщение отобра- отображается через свойство defauItStatus. Свойство defauItStatus может быть установлено в любое время — то ли после загрузки окна, то ли после его открытия. Второй способ — отображать временное сообщение поверх заданного по умолчанию текста. Фактически, это сообщение обычно появляется, когда пользователь про- продуцирует событие, например, перемещая мышь. Это со- сообщение можно устанавливать с помощью свойства status. Рисунок 15.9 иллюстрирует использование свойств defauItStatus и status. http://www.acadians.com в/ga URL ряде. p РИСУНОК 15.9. Установка свойств defauItStatus и status. Код для этой страницы показывает три действия для изменений сообщения в строке состояния. Сначала при- приведенный ниже набор кодов устанавливает заданное ш> умолчанию сообщение при открытии окна: window.defauItStatus = *->URL page. " "Welcome to the large Во-вторых, когда пользователь переходит на ссыл- ссылку "Go", ее обработчик событий onMouseOver вызыва- вызывает следующую функцию: function changeStatus (> { window, status = "Click me to go to the ^¦Acadia Software home page." 1 В-третьих, чтобы изменить текст заданного по умол- умолчанию сообщения состояния, пользователь может выб- выбрать одно из сообщений объекта Select. Когда вызыва- вызывается обработчик событий onClick кнопки "Change", он вызовет следующую функцию: function changeDefaultStatus () { window.defauItStatus = window.document.statusForm.messageList. options [window.document. statusForm. wmessageList.selectedlndexj. text I Листинг 15.7 содержит полный исходный код этоп> примера.
Объект Window Глава15 РбЗЮМб многое — как в мультифреЙМОВЫХ окнах, так и в оди- одиночных. Объекты Frame, Location и History являются В этой главе детально исследовался верхний уровень свойствами объекта Window и обеспечивают средства иерархии JavaScript-объектов. Рассмотренные объекты для работы с соответствующими экземплярами браузе- работают скорее с различными аспектами окна браузе- ра. В этой главе также обсуждалось применение JavaScript pa, нежели с HTML-дескрипторами. Как объект верх- для ссылок на объекты и свойства в других фреймах и Него уровня в иерархии, объект Window отвечает за окнах браузера. Листинг 15.7. Status.htm. <html> <head> <title>Status Bar</title> <SCRIPT LANGUAGE=" JavaScript" > window, defaultstatus = "Welcome to the large URL page." function changeStatus {) { window, status = "Click me to go to the Acadia Software home page." } function changeDef aultStatus ( ) { window, defaultstatus = window, document. statusForm.messageList. lb*options [window.document. statusForm.messageList. selectedlndex] . text } II—> </SCRIPT> </head> <body> <p>b#160;</p> <p>fi#160;</p> <p align=center> <font color="#008040"> <font size=7> <strong>http: //www. acadians. com</strongx/fontx/fbntx/p> ¦<p align=center> <a href ="http://www.acadians. com" onMouseOver="changeStatus ();return true">Go. . .</aX/p> <form name="statusPorm" method="POST"> <pXbr> <br> <br> <br> <p align=center> <font size=l>To change the default status bar message, select a message from the list below and click the Change button. </fontX/p> <p align=centerXselect name="messageList" size=l> <option selected>Welcome to the large URL page , </option> <option>En route to Acadia Software</option> <option>This page intentionally left (nearly) blank. </option> <option>An exciting example of changing status bar text. </option> </select> <input type=button name="Change" value="Change " onClick=" changeDef aultStatus () "X/p> </form> </body> </html>
Объект Document В ЭТОЙ ГЛАВЕ Объект Document Объект Link О бъектAnchor Объект Image В главе 9 был проведен краткий обзор JavaScript- объектов каждого объектного уровня, начиная с перво- первого. В той же главе кратко рассматривались объекты Document, Link, Anchor и Image, но не были детально описаны их работа и применение. Поскольку эти объек- объекты предоставляют существенные функциональные воз- возможности с точки зрения Web-разработчика, стоит по- посвятить им отдельную главу. Глава продолжает начатое обсуждение обзором этих объектов, часто называемых объектами документов. Дан- Данный набор объектов включает в себя ключевой клиент- клиентский объект Document и три его "дочерних" объекта: Link, Anchor и Image. Объект Document Объект Window является объектом самого высокого уровня для клиентских JavaScript-объектов. В этой роли он служит в качестве контейнера, но фактически может содержать не все подряд. Содержимое Web-документа оставлено для объекта Document. Объект Document иг- играет роль JavaScript-эквивалента HTML-документа и используется в качестве метода доступа к своим дочер- дочерним объектам. В этой роли объект Document является контейнером для всех HTML-объектов, которые соотносятся с деск- дескрипторами <body> и <head>. Объект Document получает значение свойства title из дескриптора <title> (располо- (расположенного в разделе <head >) и несколько связанных с цветом свойств из раздела <body>, который приведен здесь: <body ,[baekground= "bacfcyroundlmage"] [bgcolor=" backgroundColor" ] [ text="foregroundColor"] l[ link=" unfollowedLinkColor"] [alink="activatedLinkColor"] [vlink=" followedLinkColor"] [onload="mefchodName"] |[onunload="methodName"] > </body> ПРИМЕЧАНИЕ " Хотя события onLoad и onUnload могут быть захваче- захвачены обработчиками событий on Load и onUnload внутри дескриптора<Ых!у>, они являются событиями объек- объекта Window, а не объекта" Document. Объект Document — решающий во время работы с JavaScript и HTML, поскольку все действие происходит на Web-странице в пределах документа. Таким образом, придется ссылаться на объект Document при ссылке на один из объектов внутри него. Например, при обраще- обращении к объекту Form с именем invoiceForm в ссылке по- потребуется указать document: document. invoiceForm. submit () ; Если этого не сделать, JavaScript не сможет помес- поместить объект на страницу. Программное создание HTML-документов Как видно из этой книги, JavaScript можно использо- использовать для ответа на события, сгенерированные на стати- статических Web-страницах. Можно также использовать его и для визуальной генерации HTML-страниц. Фактичес- Фактически, каждый из методов объекта Document используется для запрограммированных изменений документов: • ореп(["/яшге2у/>е"])открывает поток для write() и writeln(). Его параметром может быть один из при- приведенных ниже типов MIME (text/html — по умол- умолчанию): text/html
Объект Document text/plain image/gif image/jpeg image/x-bitmap plugin (любой подключаемый mime-тип Netscape) • write (JavaScriptExpressionKamicbmaeT выражение JavaScript в документ. • write\n(JavaScriptExpression)i:&KKC записывает выра- выражение JavaScript в документ, но добавляет после вы- выражения символ новой строки. • close() закрывает поток, открытый с помощью мето- метода ореп(). В то время как методы ореп() и close() открывают или закрывают сгенерированный документ, методы tvrite() и writeln() обеспечивают содержимое документа. В качестве параметра можно использовать любое допу- допустимое выражение JavaScript, включая литерал, перемен- переменную или целое число. Например, каждый приведенный ниже пример — вполне допустимое использование write(): var loc = "Ashford, Kent" The castle is located in" + loc) document.write("I stayed in the Robert *• Courtney s room.") Г would like" + 70 + "copies of "¦•that report.") Имейте в виду, что необходимо записывать HTML- код, а не простой текст. Можно использовать HTML- дескрипторы так же, как если бы документ готовился в HTML-редакторе: document.write ('<h3>Return to the <a I- p</a> home page .</h3Xp>' ) ; На рис. 16.1 показан результат. РИСУНОК 16.1. Генерация ссылки с помощью JavaScript. Одно ключевое ограничение, которое следует иметь в виду при использовании write() или wri связано с тем, что нельзя изменять содержимое текущего доку- Глава 16 мента без полной перегрузки окна. Следующие разде- разделы описывают три допустимых метода, с ПОМОЩЬЮ ко- которых можно визуально создавать HTML-документы. Разработка документа в текущем окне Новый документ можно создавать в текущем окне при его загрузке. Этот код обычно размещают внутри деск- дескрипторов <script>, либо в разделе <head>, либо отдель- отдельно, если это возможно. Например, если требуется оп- определить браузер и скорректировать текст в соответствие с его типом, можно прибегнуть к сценарию, показан- показанному в листинге 16.1. Листинг 16.1. Генерация разного текста на Web- странице в зависимости от типа браузера. <script type="text/javascript"> <!-- var browser = navigator.appName; document. open <) ,- if(browser == "Netscape"){ document.write("<h2>Welcome <a hre?= :om'> Navigator</a> "-•user .</h2>") ; )else if(browse г == "Microsoft Internet '"Explorer") { "<h2>Welcome <a href= > 'http://www .micrc Dft.com1> Internet 1->Explorer</a>user .</h2>") ; )else{ 5nt.write("<h2>Welcome. But what r are you i ) jnt. write ("We are glad you came to our Web -«site. Do you know how") ; ' we knew your browser type?") document, close (); II </script> На рис. показан результат в Navigator 4, а на рис. 16.3 — в Internet Explorer 5. f> ?.* Vie* Qo Vnic I 2} Ou WelcomeNavigatoruser. We are glad you саше to our Web site. Do you how we knew your brc 'ser type? РИСУНОК 16.2 Настроенная страница в браузере Navigator.
Использование DOM Welcome Internet Explorer user. We are glad you come to our Web site. Don't you wish jva new how we knew your birr type? РИСУНОК 16.3. Настроенная страница в браузере Internet Explorer. Создание документа в фрейме Возможна также генерация нового документа в другом фрейме мультифреймового окна. Этот метод подобен приведенному ранее, но здесь необходимо ссылаться на нужный документ, используя точечную нотацию. На- Например, для ссылки на первый фрейм мультифреймо- мультифреймового окна используется следующий код: parent.frames[0].Document.write("test"); Листинг 16.8, который будет приведен ниже в гла- главе, демонстрирует пример программной установки до- документа в фрейме. Создание документа в отдельном окне Третья методика визуального создания документов свя- связана с открытием нового окна и записью в него созда- создаваемого документа. Если необходимо привести в отдель- отдельном окне список установленных в браузере Navigator подключаемых модулей, применяется код, показанный в листинге 16.2. Рисунок 16.4 демонстрирует результаты работы сце- сценария в браузере Navigator. Листинг 16.2. Отображение списка подключаемых модулей Navigator. <html> <head> <script type= function showWindow (){ var len = navigator.plugins.length; newWin = window.open("", ' , "height=400,width=500"); newWin.document.write("<h2>Plug-In Info : for (var i = 0; i < len; i++) { newWin.document.write ("<li>'r + navigator.plugins[i].description + newWin. document. close () II—> </script> </head> <body> <fonn> <input type="button" value="Show Plug-In ** Information" </form> </body> </html> y HPMPatfl NetscapePhig-m Netscape'- ¦ -:t" Plug-in Тата Plug-in 12.2 for Netscape Navigatorrath Я JavaFlug ш 1 2.2forNelscape NavigatorwithJTK'IK 1.;' 2(DLLHelper) Ha 1 a2forbTetscape!TavigatorwitfcJE RE 1.1 2 (DLLHelper) Netscape Plug- ink'r Acrobat Sound Playerfor Netscape -iQator.v. 1.1 QuickTime » f« Win32». 1.1.1 NPAVF2. *n ph^n DLL D-bull РЦ-п РИСУНОК 16.4. Генерация нового документа в отдельном окне. Изменение цвета документа Установки цветов документов по умолчанию определе- определены в конфигурации пользовательского браузера, одна- однако HTML обеспечивает возможность изменения этих установок, а в JavaScript можно сделать это программ- программно. Объект Document имеет пять свойств, которые пред- представляют цвета различных атрибутов в документе - aLinkCoIor, bgColor, fgColor, LinkColor и vLinkCoIor. Описание этих свойств сведено в табл. 16.1. Эти свойства выражаются либо в виде строковых литералов, либо в виде шестнадцатиричных RGB-зна- RGB-значений. Например, если требуется назначить для фона документа цвет "chartreuse", используют литерал стро- строки chartreuse: document.bgColor = "chartreuse"; Можно также использовать эквивалентное шестнад- шестнадцатиричное RGB-значение: document.bgColor = fffOO";
Объект Document Глава 16 Таблица 16. I Цветовые свойства объекта Document. Свойство HTML-атрибут <body> Описание ahnkColor bgColor fgColor linkColor vlinkColor ПРИМВШИЕ alink bgcolor text link vlink Цвет активной ссылки (после того, как кнопка мыши нажата, и до того, как она отпущена). 'Цвет фона документа. Цвет символов (текста) документа. Цвет непосещенных ссылок. Цвет посещенных ссылок. Список числовых значений цветов в JavaScript находится в табл. 5.8 в главе 5. Эта таблица содержит списки чис- числовых значений цветов как в виде строковых литера- литералов, так и в виде шестнадцатиричных RGB-значений. Шестнадцатиричный RGB-триплет — это комбина- комбинация трех шестнадцатиричных значений, соответствую- соответствующих красному, зеленому и синему составляющим цвета. За счет объединения значения формируют шестнадца- шестнадцатиричный RGB-триплет. Число должно принимать один из двух зависящих от регистра видов: rrggbb или #rrggbb. При использовании изменений цвета в атрибуте Document необходимо соблюдать те же самые принци- принципы, как и при изменении текста. Изменения можно де- делать только тогда, когда страница установлена, напри- например, в Document.write(). но не на странице, которая уже "отрисована" в окне браузера. Для объяснения способа установки цветов рассмот- рассмотрим пример, показанный на рис. 16.5. Нижний фрейм содержит список выбора со всеми цветами и группой переключателей, связанных с опциями цвета атрибута Document. Можно выбрать используемые цвет и свой- свойство, а затем нажать на кнопку "Apply". JavaScript пере- перегружает верхний фрейм с учетом проделанных установок. Листинг 16.3 содержит исходный код HTML для документа frameset. Листинг 16.4 показывает код для основной части текста, а листинг 16.5 код для ниж- нижнего фрейма, который исполняет данный процесс. Ког- Когда пользователь нажимает на кнопку "Apply", метод refreshMain() присваивает значение, зависящее от выб- выбранной в данный момент опции списка выбора, пере- переменной newColor. Затем с использованием точечной нотации выполняется ссылка на документ в верхнем фрейме (parent.main.Document) и перезагрузка верхне- верхнего фрейма на основе write() и color. Листинг 16.3. Источник для установки фреймов в Document. <hfanl> <head> <title>Color Example</title> </head> <frameset rows=S%,25%"> <frame src=63Xl6_L04 .html" name="main' marginwidth="l" marginheight="l"> <frame src=63X16_L05.html" name="colorDef" marginwidth="l" marginheight="l"> </frameset> </html> Листинг 16.4. Код основной части текста примера. <html> <head> <title>Main Body</title> </head> <body> <h2> <em> JavaScript Unleashed </an> </h2> <P> Here is some sample text Here is a sample link: <a href="http: //home. netscape. com">Netscape 'РИСУНОК 16.5.Динамическое изменение цветов фрейма. </body> </html>
, Использование DOM Часть III Листинг 16.5. Код JavaScript-сценария и выбора цветов. <html> <head> <title>Color Definition</title> <SCRIPT IANGOAGE=" JavaScript" > <! — var graf = ' <body> ' ; graf += '<h2Xem>JavaScript Unleashed</em> graf += '<p>Kere is some sample text</p>' ; graf += '<p>Here is a sample link: <a href="http://home.netscape.com"> Netscape</aX/p>' ; graf += • </body> ' function refreshMain () { var newColor = document . f orml. colorList. options {document, forml.colorList.selectedlndex],text var selProp = null with (parent.main. documentV { open ( ) ; write (graf) ; if(document.forml.type[0].checked){ bgColor = newColor }else{ if (document.forml.type [1] .checked) { f gColor = newColor ; )else{ if (document.forml. type 12]. checked) { alinkColor = newColor; }else{ if (document.forml. type [3]. checked) { linkColor ss newColor; }else if (document.forml. type {4} . checked) { vlinkColor = newColor; 1 closed > II—> </script> </bead> <body bgcolor="tomato"> <form name="forml">- <P> Select Color: <select name="colorList" size="l"> <option>black</option> <option>blue</option> <opt ion>brown</opt ion> <option>cyan</option> <option>gold</option> <option>gray</option> <option>green</option> <option>indigo</option> <option>lavender</option> <option>lime</option> <option>maroon</option> <option>navy</option> <option>olive</option> <option>orange</option> <option>pink</option> <option>purple</option> <option>red</option> <option>royalblue</option> <opt ion>silver</opt ion> <opt ion>slategray</opt ion> <option>tan</option> <option>teal</option> <option>turquoise</option> <option>violet</option> <option>white</option> <option>yellow</option> </select> <br> <input type="radio" name="type" value= "bgColor" checked>Background </input> <input type="radio" name="type" value="fgColor">Foreground</input> <input type="radio" name="type" value= "alinkColor">Activated Link </input> <input type="radio" name="type" value= "linkColor">Unvisted Link </input> <input type="radio" name="type" value= "vlinkColor">Visited Link </input> <br> <input type="button" name="Apply" value="Apply" onclick="refreshMain() " </form> </body> </html> Хотя это и не универсальный пример, им можно вос- воспользоваться для разработки намного более гибких сце- сценариев визуального изменения цветов. 5СОВЕГ *¦-¦¦ "},, ¦ ¦'¦.. '¦ V,,"' ¦: ¦''''-' '' ¦¦ -:;\ "¦ За более общими примерами использования цветов в документах стоит обратиться к hldaho Color Center на сайте htfp:/ /www.hidaho.com/colorcenter/. Объект Link Возможно, миром правит любовь, однако WWW-миром правят ссылки. HTML-ссылки — основные элементы любого документа сети, позволяющие переходить на другие Web-страницы с помощью простого щелчка. Рас- Расположение документа несущественно; он может нахо- находиться на том же самом сервере либо за тысячи кило- километров от него. Все, что требуется обеспечить — это допустимость данного URL. JavaScript-эквивалент ги- гипертекстовой ссылки — объект Link, который опреде- определяется в HTML-синтаксисе так: [name="objectName" I [ targe t="windowName"J [onclick="jnefchodWaine"] toimouseover=" methodWame" ] > HnkText
Объект Document СОВЕТ Дополнительная информация по событиям объекта Link находится в главе 14. : ¦ - . . - . Объект link имеет несколько свойств, аналогичных параметрам для объекта Location. Они включают в себя hash, host, hostname, href, pathname, port, protocol и search. В главе 9 можно найти дополнительную инфор- информацию по этим свойствам. Ссылки на объекты Link Объекты Link не имеют свойства name, поэтому невозмож- невозможно отдельно сослаться на определенный объект Link. Единственный способ — сослаться на объект Link в коде JavaScript-сценария, используя массив dociiment.links. Массив document.links — это совокупность всех ссылок в пределах текущего документа. Порядок массива соот- соответствует порядку расположения ссылок в исходном файле. Ниже будет представлен пример, который де- демонстрирует способ использования массива document.links для обращения к отдельному объекту Link. Предположим, что требуется извлечь адреса URL из каждой ссылки на странице и перечислить их на дру- другой странице. Используя три фрейма, можно выбрать нижний фрейм в качестве "свободного" окна, которое будет использоваться для просмотра, верхний фрейм будет содержать кнопку, инициирующую процесс, а средний фрейм — создавать список URL. Рисунок 16.6 показывает три фрейма в окне Internet Explorer после вы- выполнения всего процесса. Л>П 1Ь 7»ie JavaScript 1мцазд« 4) Fundamental* oftht, JavaScript language 5) Control Structures and Looping 6) Opuru.irr PaW 1П: JuvaSatol OIiImh 3) Fundamentals °f Object- Oiientatioir 9) Handling 10) JavaScript Built-in Objert Modal вяиаш РИСУНОК 16.6. Получение информации об URLc помощью массива ссылок. Листинг 16.6 содержит код установки фреймов, ли- листинг 16.7 показывает код для нижнего фрейма, кото- который содержит все строки текста, а листинг 16.8 дает ис- исходный JavaScript-код для верхнего фрейма, в котором обрабатывается данный пример. При щелчке на кнопке "Extract Link Information" вызывается метод getLink!nfo(). Глава 16 Этот метод обращается к массиву ссылок нижнего фрей- фрейма (с именем bFrame) и устанавливает переменную len равной его длине. При записи в средний фрейм метод последовательно проходит через каждый элемент в мас- массиве ссылок и отыскивает значение свойства href. Листинг 16.6. Исходный код установки фреймов. <html> <head> <title>New Frameset</title> </head> <frameset rows="80,*,185"> <frame src=63Xl6_L08 .html" name="tFrame" marginwidth=" marginheight="> <frame src="about:blank" name="mPrame" marginwidth=" marginheight="> <frame src=63Xl6_L07.html" name="bFrame" marginwidth=" marginheight="> </frameset> </html> Листинг 16.7. Исходный код нижнего фрейма. <html> <head> <title>Links</title> </head> <body> <h2>Launching Pad</h2> <table width="80%"> <tr> <td width=5%"> <em> ¦<strong> Software </strong> </em> </td> <td width=5V> <em> <strong> Magazines </strong> </em> </td> <td width=5%"> <em> <strong> Search </strong> </em> </td> <td width=5%"> <em> <strong> JavaScript </strong> </em> </td> </tr> <tr> <td width=5%"> <a href= "http://www.borland.com">Borland</a> </td> <td width=5%">
Использование DOM Часть III <а href="http://www.informant.eom">Web Informant</a> </td> <td width=5%"> <a href="http://www.excite.com">Excite </aX/td> <td width=5%"> <a href= "http://www.gamelan.com">Gamelan</a> </td> </tr> <tr> <td width=5%"> <a href= "http://www.microsoft.com">Microsoft </aX/td> <td width=5%"> <a href= "http://www.javaworld.com">JavaWorld </aX/td> <td width=5%"> <a href="http://www.yahoo.com">Yahoo </aX/td> <td width=5%"> <a href="http://www.c2.org/-andreww/ ^javascript "> JavaScript Index</a> </td> </tr> <tr> <td width=5%"> <a href= "http://home.netscape.com">Netscape </aX/td> <td width=5%"> <ahref ="http: //www.pcweek.com">PCWeek </aX/td> <td width=B%"> <a href= "http://www.altavitsa.digital.com"> Alta Vista</a> </td> <td width=S%"> <a href="http://www.intercom.net/user/ wmecha/Java/index. html" >JavaScrip t Res. Center</a> </td> </tr> <tr> <td width=S%"> flnbsp; </td> <td width=5%"> <a href= "http://www.infoworld.com">InfoWorld </aX/td> <td width=5%"> <a href="http://home.netscape.com/ yiescapes/search/search4 .html"> Netscape Search Page</a> </td> <td width=5%"> <a href="http://home.netscape.com/misc/ '¦'developer/conference/proceedings "> Netscape Conference</a> </td> </tr> </table> </body> </html> Листинг 16.8. Исходный код верхнего фрейма. <html> <head> <base target="iniddle"> <script type="text/javascript"> function getLinklnfoO { var len = parent.tFrame.document.links.length; with (parent. tnFrame. document) ( open(); write ("<h3>The " + len + " Links of *-*The Top Frame Include: </h3Xp>") ; for (var i = 0; i < len; i++) { write((i +1) + ". » + parent.tFrame.document.links[i].href + I close () </script> </head> <body bgcolor="red"> <form> <div align="center"> <input type="button" name="Extract" value="Extract Link Information" onclick="getLinkInfo{)"> </form> </body> </html> Выполнение JavaScript-кода для ссылок Используя javascript в качестве элемента протокола href ссылки, можно выполнять выражение JavaScript вмес- вместо обычного действия ссылки (вместо перехода на но- новую Web-страницу или отправки сообщения по почте). Однако, выполняемый код должен быть самодостаточ- самодостаточным. Нельзя ссылаться на другой объект вне его кон- контекста, например, на другое окно. Ссылку можно использовать для определения типа пользовательского браузера, как показано в следующем коде: <а href = " javascrxpt:if (navigator.appName ! = "¦•'Netscape') { alert ('You should not have ¦-»clicked this link! • > ) else ( "*alert ("Thanks for clicking.')} "> All Netscape users, click me</a> В качестве второго примера приведем оглавление первого издания этой книги в HTML-документе со ссылками на каждую ее часть. Для атрибута href этих ссылок описание каждой части помещается в окно сиг- сигнального сообщения. Листинг 16.9 показывает HTML- код для данного примера, а рис. 16.7 — результат пос- после щелчка на ссылке "Part Ш".
Объект Document Глава 16 Листинг 16.9. Создание оглавления со ссылками document.alertQ. <html> <head> <title>JavaScript Unleashed Table of Contents</title> </head> <body> <a href =" javascript: alert I ' In this first section, you will get a complete introduction to ^* JavaScript . Chapter 1 takes a unique look at JavaScript, focusing on how and where it fits w into the Web application development framework- You will also see how it relates to other Web *•» technologies both on the client- and server-side. Next, in Chapter 2, you will learn about wthe relationship between JavaScript and Hypertext Markup Language (HTML) and how the browser ^interprets your code at runtime. Chapter 3 looks at the software tools you need to develop in **JavaScript. ' ) "> <h3>Part I: Getting Started with JavaScript</h3> <h4> 1) JavaScript and the World Wide Web <br> 2) How JavaScript and HTML Work Together <br> 3) Assembling Your JavaScript Toolkit </h4> ¦<a hre?=" javascript : alert ( 'The second part presents a thorough look at the JavaScript language. wIn Chapters 4-7, you will learn about language basics, control structures, operators, and, ¦¦«functions. ¦ ) "> <h3>Part II: The JavaScript Language</h3> </a> <h4> 4) Fundamentals of the JavaScript Language<br> 5) Control Structures and Looping <br> 6) Operators<br> 7) Functions </h4> <a href=" javascript : alert ( "Part three dives into the heart of JavaScript -- objects. After an ^introduction to object-oriented concepts in Chapter 8, Chapter 9 looks at how you can handle *-*user and system events. Chapter 10 then looks at the built-in JavaScript hierarchy and introduces ^you to each of the Navigator and Built-in language objects ¦ Chapters 11-14 continue where the '-'previous chapter left off by exploring in-depth each of the built-in JavaScript objects. '•Chapter 15 rounds out the discussion on objects, focusing on how you can create your own. It ¦"¦includes many innovative ideas related to custom object development within JavaScript. ' ) "> <h3>Part III: JavaScript Objects</h3> </a> <h4> 3) Fundamentals of Object-Orientation <br> 9) Handling Events <br> 10) JavaScript Built-in Object Model <br> 11) Navigator Objects <br> 12) Document Objects <br> 13) Form Objects <br> 14) Built-in Language Objects <br> 15) Creating Custom JavaScript Objects <h4> ¦<a href=" javascript: alert { 'The next section builds upon everything you learned up to that point wto look at specific areas of interest to the JavaScript developer. Chapter 16 explores how you ^can enhance HTML forms with JavaScript, such as providing client-side data validation. Both ^Chapters 17-18 really focus on frames and how you can use JavaScript in multi-frame windows. '¦•I have found frame management to be perhaps the most common use of JavaScript on the Web. ^•Chapter 19 looks at yet another key topic, cookies and other techniques for handling and ¦^maintaining state in the stateless environment of the Web.')"> <h3>Part IV: JavaScript Programming</h3> </a> <h4> 16) Enhancing Forms with JavaScript <br> 17) Working with Frames and Windows<br> 18) Scripting Outlines and Table of Contents <br> 19) Cookies Samp; State Maintenance </h4> <a href=" javascript : alert ( "While Parts I-IV focused on client-side JavaScript, this section ^focuses on its server-side counterpart. Within Netscape LiveWire and other products such as
Использование DOM Часть III «Borland IntraBuilderr you can use JavaScript as a server-side scripting language - In doing so, w you are freed from wr i t ing CGI s cr ipt s and deal ing wi th such language s as PERL - Chap t e r 2 0 '^ looks at server-side JavaScript, focusing on LiveWire and IntraBuilder. Chapter 21 takes look «at the issue of how to architect client/server applications on the Web- Covered are many of wthe issues you will encounter as you plan such an application. ' ) "> <h3>Part V: JavaScript on the Server</h3> </a> <h4> 20) Server-Based JavaScript <br> 21) Partitioning Client and Server Applications </h4> <a href=" javascript: alert ( ' Part VI explores five advanced subj ects, many of which are emerging «as key topics as JavaScript matures - Chapter 22 dives into Error Handling and Debugging «JavaScript applications. Chapters 23-24 cover the hot topic of integrating JavaScript with «Netscape Plug-Ins and ActiveX controls. Chapter 2 5 looks at integrating JavaScript with VRML «and multimedia data. Chapter 2 6 closes the section by looking at a more conceptual topic-* «JavaScript security- The chapter not only looks at the key issues surrounding this subj ect, «but provides some helpful advice as you consider using JavaScript for your Web site. ' ) "> <h3>Part VI: Advanced JavaScript</h3> <h4> 22) Error Handling and Debugging in JavaScript <br> 23) Working with Netscape Plug-ins <br> 24) ActiveX Scripting with JavaScript ^эг> 25) VRML and Multimedia <br> 26) JavaScript and Web Security </h4> <a href=" javascript: alert ( ' JavaScript is an important tool to glue HTML and Java applets. «In this section, we will look at Java from a JavaScript perspective in Chapter 27 and see '«how similar or different the language is for JavaScripters . Chapter 2 8 provides a good '«introduction on how to build a Java applet, while Chapter 29 is where the rubber meets the «road when it focuses on integrating Java and JavaScript - ' ) "> <h3>Part VII: Java and JavaScript</h3> <h4> 27) Java from a JavaScripter Perspective <br> 28) Building Java Applets<br> 29) Integrating JavaScript with Java </h4> <a href =" javascript: alert ? 'Many corporations will use the Web as a way to get at their data. «As a result, how JavaScript can access data will be an increasingly important topic as the «technology matures. In this section, we will look at how you can work with data both on the «client-side and server-side- Chapter 30 introduces the notion of maintaining lookup tables «on the client side to lessen the need to access the server- Chapter 31 then gets into how «you can use JavaScript to access server-side data- LiveWire and IntraBuilder will again be «used in this context. ') "> <h3>Part VIII: JavaScript Database Applications</h3> <h4> 30) Using Client-Side Tables in JavaScript <br> 31) Working with Server-Side Database Objects </h4> <a href=" javascript : alert { 'The final section provides some extra information that will assist '«you as you read the book. Appendixes A-B provide basic references on the JavaScript and HTML «respectively- Appendix С looks at how VBScript and JavaScript compare- Appendix D lists «JavaScript resources that are available online . ' ) "> <h3>Part IX: Appendixes-;/h3> </a> <h4> A) JavaScript Language Summary <br> B) Fundamentals of HTML <br> ¦C) Comparing JavaScript with Microsof tS#14 6 ;s VBScript <br> D) JavaScript Resources on the Internet <h4> </body> </html>
Объект Document Глава 16 Vftl I ! I: lite JavaScript I.№g!i3&( 4) Fundamental* of the JnvaXeript Language 5) Control 5 tucIum and Looping 6) Operator* 7) Rind Part ГО: «Jmva,Scrfo< О1>|*пе I 8) Fundamentals of Object-Orientation | 9) Handling Events 10) Ja*»SrnPt Built-in Object Model РИСУНОК 16.7. Щелчок на ссылке отображает окно сигнального сообщения. Объект Anchor Наиболее часто объект Link используется для перехода на другую Web-страницу или другое место в текущем документе. В пределах текущего документа ссылка ука- указывает на место в тексте, которое называется якорем (anchor). В HTML-синтаксисе он определяется так: <а [href=IocationOrDRL] name="objectWame" [target="windowName" ]> anchorText Можно сказать, что объект Anchor — поистине гость для JavaScript. С помощью якорей в JavaScript можно сделать немногое. Сам по себе объект Anchor не имеет никаких свойств, методов или событий. Единственный способ его применения в JavaScript — с помощью мас- массива anchors объекта Document. Массив document.anchoi используется для определения количества якорей в документе и выполнения необходимых итераций по ним. Объект Image ПРИМЕЧАНИЕ Объект Image поддерживается в JavaScript 1.1 и сле- следующих версиях. Его не поддерживают JavaScript 1.0 и JScript 1.O. Тем, кто провел достаточно много времени в Web, должно быть, понятно, насколько важна для Web гра- графика. Едва ли существуют страницы, вообще не имею- имеющие графических элементов. Объект Image, новый в Navigator 3, представляет HTML-изображение, которое определяется в следующем формате: <img [name="objectWame" ] src="Location" [lowsrc="Location" ] [height="Pixels"|"VaIue"%J [width="Pixels"I"Value"%] [hspace="Pixeis"] [wspace="Pixe!s"] [border="Pixels"] [align="left"|"right" I "top"| "absmiddle"|"absbottom"| "texttop"|"middle"|"baseline"| "bottom"] [ismap] [usemap=" Location#MapName"\ [onabort="methodName"} [onerror="methodName"] [onload="me thodName"] > СОВЕТ Дополнительная информация Image находится в главе 14. о событиях объекта Например, для вывода изображения dot.gif в HTML- коде необходимо воспользоваться следующим синтак- синтаксисом: <img src="dot.gif" height=0i Экземпляр объекта Image создается с помощью ко- команды new: CompanyLogo = new CompanyLogo.sro = Image(); "logo.gif"; Размеры графического элемента можно передавать как параметры в конструктор Image(). Например, если требуется отобразить логотип размером 200x300 пиксе- пикселов, используется код: CompanyLogo = new Image B00,300); CompanyLogo.sre = "logo.gif"; Присваивая значение свойству sre, можно изменять отображаемый графический элемент. Однако, при этом в область и: тя загрузится новый URL или гра- графический элемент. Поскольку изображение определяется только с по- помощью дескриптора <img>, создаваемый объект Image обладает достаточно ограниченными возможностями. Его можно использовать для получения изображения до того, как оно станет фактически необходимо для пока- показа на дисплее. Поскольку изображение в этом случае хранится в памяти, при перегрузке документа оно бу- будет намного быстрее отображаться. Наиболее общий пример — анимационная последовательность изображе- изображений, которые получаются с использованием объекта Image и позже отображаются из памяти.
Использование DOM Часть III f СОВЕТ ,,.,,;. v • ¦ . т ^ В главах 20 и 21 можно найти дополнительную инфор- информацию по способам применения объектов Image. Резюме Объекты документа, рассмотренные в этой главе, явля- являются JavaScript-эквивалентами ряда базовых HTML-эле- HTML-элементов. К таким объектам относятся Document, Link, Anchor и Image. Хотя JavaScript используется для рас- расширения или получения информации из этих объектов, многие JavaScript-взаимодействия обычно исходят из работы с формами. Поэтому в следующей главе объек- объекты Form рассматриваются более детально.
Объекты Form В ЭТОЙ ГЛАВЕ Объект Form Объект Text Объекты Button: Submit, Reset и Button Объект Checkbox Объект Radio Объект Select Объект Password Объект Hidden Одним из ключевых достижений в развитии Web было появление HTML-форм в мире статических стра- страниц. За счет форм Web фактически может обеспечить нечто большее, нежели однонаправленный режим свя- связи. Формы предоставляют средства, с помощью которых любой пользователь на любой машине сможет передать данные на сервер для обработки. Благодаря JavaScript, HTML-формы получают гораз- гораздо более широкие возможности. Теперь можно не толь- только предварительно обрабатывать данные формы до от- отправки их пользователю, но также использовать формы в приложении, которое полностью находится на сторо- стороне клиента. В главе рассматривается объект Form и мно- множество объектов, которые он может содержать, включая объекты Text, Button, Radio и Select. Цель этой главы -• предоставить вкратце всю информацию, касающуюся форм, и в то же время дать несколько действительно полезных советов. Кроме того, можно воспользоваться примерами этой главы в качестве шаблонов, что поможет сэкономить время при разработке сайтов. Для копирования шаблона нужно просто посмотреть на листинги и на их общую структуру, и затем подкорректировать код под собствен- собственные потребности. Все больше и больше разработчиков следуют этому рецепту, а данная глава предоставляет изрядное число подходящих шаблонов. ^примечание „Щ1 Объекты Form, обсуждаемые в этой главе, могут су- существовать только в пределах формы, но не вне ее. Объект Form Одна из основных целей JavaScript — обеспечить сред- средства для взаимодействия с пользователем на стороне клиента. В большинстве случаев это взаимодействие с о !. 158 пользователем происходит с помощью HTML-формы. Таким образом, JavaScript-объект Form — важный объект в объектной модели JavaScript. С самим объек- объектом Form не многое можно сделать. Выражаясь кратко, объект Form — это контейнер, содержащий введенные пользователем данные. В HTML объект Form определяется так: <FORM [NAME=" ?orwName" ] [ACTION="serverVRL" ] i[ENCTYPE=" encodingType"] [METHOD=GET | TOST] [TARGE T="windowNaine" ] [onSubmit=" methocfflame" ] > </FORM> Для определения формы используют стандартные условные обозначения HTML: < FORM NAME = "Forml" ACTION= "http://www.acadians.com/js/script,jfm" METHOD=GET > <!— Здесь должны следовать объекты формы —> </FORM> ^ПРИМЕЧАНИЕ-: Щ^Х м;_>-,, Дополнительная информация по использованию форм в JavaScript находится в главе 29. Отправка формы на сервер До JavaScript единственное реальное назначение HTML- формы состояло в отправке на сервер элементов данных, собранных на стороне клиента. Поскольку на стороне клиента не было достаточно возможностей для обработ- обработки данных, они посылались серверу, который затем реагировал на полученную информацию. JavaScript по- позволяет теперь передавать обработку данных HTML-
Использование ЮМ Часть III формам, хотя это не устраняет потребность отправки формы на сервер. Можно отправлять форму, используя один из двух процессов. Во-первых, можно вызвать метод submit() объекта Form, а во-вторых — нажать на кнопку "Submit", которая автоматически отправит соответствующую ей форму. ^ПРИМЕЧАНИЕ? В главе 14 приводится дополнительная информация по реализации с помощью JavaScript проверки допустимо- допустимости данных перед отправкой формы на сервер. Многие из свойств объекта Form работают с допол- дополнительной информацией, которую форма отправляет на сервер. Эти свойства перечислены ниже: • action (то же, что и параметр ACTION=). Свойство action определяет URL сервера, куда отправляется форма. forml.action = "http://www.aoadians.com/js/ ** surv. cgi " Это обычно программа CGi, приложение LiveWire или файл IntraBuilder JFM. • enctype (то же, что и параметр ENCTYPE=). Свой- Свойство enctype определяет MIME-кодирование формы. Значение по умолчанию — appIication/x-www-Form- urlencoded: if (forml. enctype == ^urlencoded") { alert("Encoding "application/x-www-form- type is normal.") ) ¦• method (то же, что и параметр METHOD=). Свой- Свойство method определяет, каким образом форма от- отправляется серверу. Наиболее часто применяется значение GET, однако можно использовать также и Листинг 17.1. formSubmithtm. POST. Этот параметр основан на процессе со сто- стороны сервера, поэтому при проектировании HTML- форм необходимо учитывать требования программы сервера. Следующий код показывает пример исполь- использования параметра method. var methodType methodType = forml.method alert ("The method type for this form is: " + methodType) • target (то же, что и параметр TARGET=). Свойство target определяет целевое окно, которому сервер дол- должен послать ответную информацию. Если свойство target не определено, сервер отображает результаты в окне, отправившем форму. Если используется мультифреймовое окно, свойство target определяет- определяется для фрейма с помощью параметра NAME деск- дескриптора <FRAME>. Можно также использовать одно из следующих зарезервированных имен окон: _top, _parent, _self или Jbhink- Но не забывайте, что это спецификация HTML, а не JavaScript. Нельзя указывать JavaScript-имя объекта Window, такое как parent.resultsWindow. Следующий код демонстрирует пример использования этого свойства: if (document.forml.newWindowCheckBox.checked) ( document.forml.target = "resultsForm" ) else { document.forml.target = "_self" ) HTML-форма, показанная в листинге 17.1, исполь- использует для отправки формы комбинацию HTML-дескрип- HTML-дескрипторов и JavaScript-кода. Обратите внимание, что свой- свойство action объекта Form получает новое значение в течение события onSubmit объекта Form, если пользо- пользователь установил флажок в "Rush Order". Программная установка свойства action отменяет его значение по умолчанию. <html> <head> <title>For More Information</title> <SCRIPT LANGUAGE="JavaScript"> function checkType() { if (document.forml.rush.checked) { document.forml.action = "http://www.acadians.com/js/rush.cgi" } </SCRIPT> </head> <body> <hl>Order Form</hl> <hr> <form name="forml" action="http://www.acadians.com/js/order.cgi" method="POST" onSubmit="cheekType()"> <p>Please provide the following contact information:</p> <blockquote> <preXem> First name </emXinput type=text size=25 maxlength=256 name="Contact_FirstName"> <em> Last name </emXinput type=text size=25 maxlength=256
Объекты Form Глава 17 name="Contact_LastName"> <em> Title </emXinput type=text size=35 maxlength=256 name="Contact_Title"> <em> Organization </emXinput type=text size=35 maxlength=256 name="Contact_Organization"> <em> Work Phone </emXinput type=text size=25 maxlength=25 name="Contacfc_WorkPhone"> <em> FAX </emXinput type=text size=25 maxlength=25 name="Contact_FAX"> <em> E-mail </emXinput type=text size=25 maxlength=256 name="Contact_Email"> <em> URL </emXinput type=text size=25 maxlength=25 name="Contact_URL"> </pre> </blockquote> <p>Please provide the following ordering information:</p> <blockquote> <preXstrongXJTY DESCRIPTION </strongXinput type=text size=6 maxlength=6 name="Ordering_OrderQty0"> <input type=text size=45 maxlength=256 name="Ordering_OrderDescO"> <input type=text size=6 maxlength=6 name="Ordering_OrderQtyl"> <input type=text size=45 maxlength=256 name="Ordering_OrderDescl"> <input type=text size=6 maxlength=6 name=rdering_0rderQty2"> <input type=text size=45 maxlength=256 name=rdering_0rderDesc2"> <input type=text size=6 maxlength=6 name=rdering_0rderQty3"> <input type=text size=45 maxlength=256 name=rdering_OrderDesc3"> <input type=text size=6 maxlength=6 name=rdering_0rderQty4"> <input type=text size=45 maxlength=256 name="Ordering_OrderDesc4"> <em> </emXstrong>BILLING</strong> <em>Purchase order # </emXinput type=text size=25 maxlength=256 names"Ordering_PONumber"> <em> Account name </emXinput type=text size=25 maxlength=256 name="Ordering_POAccount"> <em> </emXstrong>SHIPPING</strong> <em> Street address </em><input type=text size=35 maxlength=256 name="Ordering_StreetAddress"> <em> Address (cont.) </emXinput type=text size=35 maxlength=256. name=rdering_Address2"> <em> City </emXinput type=text size=35 maxlength=256 name="Ordering_City"> <em> State/Province </emXinput type=text size=35 maxlength=256 name="Ordering_State"> <em> Zip/Postal code </em><input type=text size=12 maxlength=12 name="Ordering_ZipCode"> <em> Country </emXinput type=text size=25 maxlength=256 name="Ordering_Counfcry"> </pre> <preXinput type=checkbox name="rush" value="ON">Rush Order!</pre> </blookquote> <pXinput type=submit value="Submit Form"> <input type=reset value="Reset Form"> </form> </body> </html> Для получения дополнительной информации об обра- обработчике событий onSubmit обратитесь в главу 14. Проверка элементов в Form Form действует как контейнерный объект для всех дру- других объектов формы. Поскольку эти типы объектов (на- (например, объекты Text или Button) нужны для взаимо- взаимодействия с пользователем, можно относиться к ним как к объектам пользовательского интерфейса (Ш-объектам). Объект Form имеет свойство elements, которое приме- применяется для ссылки на элемент формы или перебора всех элементов в форме для специфических задач. Порядок массива полностью основан на порядке следования эле- элементов HTML-формы в исходном файле. Первый пере-
Использование DOM Часть III численный элемент — elements[0], второй — elements[l] и т.д. Можно ссылаться на каждый элемент Form с помо- помощью имени либо его индекса в массиве элементов. На- Например, если объект Text с именем LastName является первым элементом в форме, на него можно ссылаться с помощью следующего кода: custLastName = Forml.elements [0].value Кроме того, допускается также и такой код: custLastName = Forml.LastName.value Свойство elements применяют для работы с каждым объектом формы. Предположим, необходимо удостове- удостовериться, что каждое поле в форме не является пустым. Используя свойство elements, можно создать цикл for для выполнения итераций по каждому элементу мас- Листинг 17.2.formElements.htm. сива и проверки значений. Этот код показан в лис- листинге 17.2. Обратите внимание, что следующие процедуры про- проверки достоверности формы не проверяют правиль- правильность ввода значения года. Для получения дополнитель- дополнительной информации относительно полезных методов проверки правильности обратитесь в главу 29. Несложно заметить, что метод checkFields() для оп- определения количества итераций в цикле for использует свойство elements.length. Далее, поскольку массив elements включает в себя все объекты формы, в том чис- числе и два объекта Button, операция typeof используется для определения типа элемента перед проверкой его зна- значения. На рис. 17.1 показано сигнальное окно сообщения, которое появляется в случае нахождения пустого поля. <html> <head> <title>Online Registration</title> <SCRIPT LANGUAGE="JavaScript"> <\ — function checkFields (> {. var num = document.forml.elements.length var validFlag = true for (var i=0; Knum; i++) { if ((document.forml.elements[i] .value = null I I. document.forml.elements[i].value = "") S& (typeof document.forml.elements[i] != 'submit' I I typeof document.forml.elements[i] != 'reset')) I] validFlag = false alert ("The " + document, forml. elements [1] . name + " field Is blank. Please enter a value.") break } 1 return validFlag </SCRIPT> </head> <body> <form name="forml" method="POST" onSubmit="return checkFields()"> <h2>Online Registration</h2> <p>Osername:<br> <input type=text size=25 maxlength=256 name="Username"Xbr> Category of Interest :<br> <input type=text size=25 maxlength=256 name="Category"Xbr> Starting Year:<strongxbr> </strong><input type=text size=25 maxlength = 256 name="StartYear"xbr> Email address :<strong><br> </strong><input type=text size=25 maxlength=2S6 name="EmailAddress"X/p> <h2xinput type=submit value="Register"> <input type=reset value="Clear"X/h2> </form> <p>snbsp;</h5> </body> </html>
Объекты Form [РИСУНОК 17.1. Проверка значений полей в форме. Объект Text Для большинства задач объект Text — это элемент, ко- который наиболее часто используется для хранения дан- данных, вводимых пользователем. Объект Text используется для захвата однострочной произвольной информации. Для многострочной информации применяется объект Textarea, обсуждаемый в разделе "Объект Textarea". Как и другие объекты Form, объект Text реализует "объект- "объектную" версию HTML-дескриптора и имеет следующий синтаксис: <INPUT TYPE="text" [NAME="objectName" ] [VALUE=" value"] [SIZE=size] [MAXLENGTH=size] Листинг 17.3. textDefaultValueWrite.htm. Глава 17 f onBlur= "method/tame"] t onChange= " me thodName "] [ onFocus="me thodName "] [onSelect="aie thodName"] > Например, чтобы определить объект Text для пос- последнего имени, используют следующее: <INPUT TYPE="text" NAME=LastName SIZE=20 MAXLENGTH=25> ПРИМЕЧАНИЕ Для получения дополнительной информации о событи- событиях объекта Text, таких как onBlur, onChange, onFocus и onSelect, обращайтесь в главу 14. Присваивание объекту Text значения по умолчанию Иногда требуется присвоить объекту Text значение по умолчанию. Если HTML-документ создается визуально, это можно сделать, определяя параметр VALUE= деск- дескриптора <INPUTtype=text>. Предположим, что требу- требуется автоматически проверить тип объекта Navigator и ввести эти данные в форму. Код из листинга 17.3 гене- генерирует форму, показанную на рис. 17.2. Обратите вни- внимание, что поле "Browser" заполняется автоматически, когда сценарий проверяет свойство appName объекта Navigator. Второй способ присваивать значение по умолчанию объекту Text связан с установкой его свойства value. Например, можно создать ту же самую форму, исполь- используя код, показанный в листинге 17.4. В этом примере значение полю "Browser" присваивается в обработчике событий onLoad. "Username"Xbr>' <SCRIPT LANGUAGE="JavaScript"> var browserVar = navigator . appName document.write ( '<body>') document, write < '<form name="forml" method="POST">' ) document.write ( '<h2>OnlineRegistration</h2>' ) document .write( ' <p>Username <br>' ) document.write ( '<input type=text size=25 maxlength=256 name= document.write( 'Browserused:<br>' > document.write( '<input type=text size=25 maxlength=2 5 6 name="Browser" value= ' "Xbr>' > Email address:<strong> <br>'> document.write ( '</strongXinput type=text size=25 maxlength=256 ' ) document .write ( ' name="EmailA<idressl1X/p>)r document, write ( '<h2Xinput type=submit value="Register"> ') document.write ( '<input type=reset value="Clear"x/h2>' ) document.write ( '</form>'> document.write ( '</body>') document.write ( '</html>') browserVar ч document.write ( // —> </SCRIPT>
Использование DOM Часть III Online Registration usemare Emai РИСУНОК 17.2. Установка значения no умолчанию. Это может показаться странным, но свойство default Value в этом примере не используется. Хотя мож- можно присваивать значение свойству default Value, форма при этом не изменяется. Поэтому следует использовать свойство value (см. листинг 17.4). Листинг 17.4. textDefaultValue.htm. <html> <head> <title>Online Registration</title> <SCRIPT IANGUAGE="JavaScript"> <! — function findBrowser() { document.forml.Browser.value = navigator.appName </SCRIPT> < /h.ead> <body onLoad="findBrowser()" > •<form name="forml" method="POST"> <h2>Online Registration</h2> <p>Username:<br> <input type=text size = 25 maxlength=2S6 name="Username"><br> Browser used: <br> <input type=text size=25 maxlength=256 name="Browser"Xbr> Email address :<strong> <br> </strongXinput type=text size=25 maxlength=256 name="EmailAddress"X/p> <h2Xinput type=submit value="Register"> <input type=reset value="Clear"X/h2> </fonn> </body> </html> СОВЕТ Свойство defauItValue полезно для получения значения по умолчанию объекта Text, но не для установки упо- упомянутого значения. Выделение текста в фокусе По умолчанию при вводе объекта Text позицией ввода является курсор. Если поле в данный момент содержит текст и требуется печатать поверх него, придется выде- выделить текст, удалить его и ввести новое значение. Мож- Можно сделать это по-другому, используя метод select() объекта Text. Листинг 17.5 показывает HTML-форму с четырьмя объектами Text, каждый из который вызыва- вызывает this.selectO в момент прихода события onFocus. В ре- результате, когда пользователь вводит текст в любое из полей формы, он автоматически выделяется. Рисунок 17.3 демонстрирует результат. Листинг 17.5. textSelecthtm. <html> <head> <title>Online Regis tration</title> </head> <body> <form name="?orml" method="POST"> <h2>Online Registration</h2> <p>Username:<br> <input type=text size=25 maxlength=256 name="Use rname" onFocus="this.select()"><br> Browser used:<br> <input type=text size=25 maxlength=25 name="Browser" onFocus="this . select () "Xbr> Email address :<strong> <br> </strongXinput type=text size=25 maxlength=256 name="EmailAddress" onFocus="this. select() "x/p> <h2xinput type=submit value="Register > <input type=reset value="Clear"X/h2> </form> </body> </html> РИСУНОК 17.3. Текст подсвечивается автоматически.
Объекты Form Захват данных с помощью объекта Textarea Все другие объекты Form предназначены для захвата данных ограниченного размера (менее 256 символов). Объект Textarea обеспечивает средства для захвата ин- информации, недоступной для простых текстовых полей, переключателей или списков выбора. Можно использо- использовать объект Textarea для ввода данных произвольной формы, занимающих несколько строк. Ввод ограничен отображением текста ASCII, однако допускается базо- базовое форматирование (например, параграфов). Объект Textarea определяется с помощью стандартного синтак- синтаксиса HTML: <TEXTAREA NAME=" objectName" ROWS="numRows" COLS="numCols" [WRAP="off|virtual|physical"] [onBlur="me thodName"] [onChange="methodNaine"] [onFocus="jnetiodName"] [onSelect="methodName" ]> displayText </TEXTAREA> Например, при использовании Textarea для передачи по сети комментариев объект определяется следующим образом: rows=12 cols=78> На рис. 17.4 показана результирующая форма. <textarea name="Comments </text are a > Comments EnteryourcommerAs Inlhespace provided telow: 1 *тя «vased to яее that you did run » itor? on "Нои со Develop J«v* .pplets ш 20 Bibugm". 1 did bat think It could be done, buc ynu proved n: WEong. Aitec readlna tbe article, I aat down and wrote w/ lirst Java .pplHE -- nciniilc» wish №^L dncithPH BMdttttrttT -- It 317ЛГ it ¦nlnntf-л. Cb>rlei се* 3V РИСУНОК 17.4. Объект Textarea. ПРИМЕЧАНИЕ Дополнительная информация о событиях Textarea (та- (таких ка< onBlur, onChange, onFocus и onSelect) может быть найдена в главе 14. . : .- : :;- ....... ... ..... ,.., ,,.....,. Глава 17 'Перенос текста в объекте Textarea По умолчанию в объекте Textarea текст не переносит- переносится. Пользователь должен вручную обозначать новую строку (с помощью клавиши "ENTER"). Однако, учи- учитывая, что такая работа вряд ли вызовет энтузиазм, вы- выполняется установка опции переноса текста с помощью параметра WRAP= HTML-дескриптора <TEXTAREA>. Помимо off (опции по умолчанию), существуют еще две дополнительных опции: virtual. Если параметр WRAP= установлен в virtual, строки переносятся на экране на границе области объекта Textarea, однако новая строка определяет- определяется только через нажатие клавиши "ENTER". physical. Если параметрWRAP= установлен в physical, строки переносятся на экране, а при отправке дан- данных на сервер в конце каждой экранной строки ус- устанавливается символ возврата каретки. Объекты Button: Submit, Reset и Button Ввиду того что графические среды в течение прошлого десятилетия стали доминирующими, кнопка представ- представляет собой, возможно, наиболее распространенный из всех компонентов пользовательского интерфейса. В HTML существует три типа кнопок, которые можно использовать в формах: Button, Submit и Reset. Как ви- видите, два из них являются специализированными фор- формами универсального объекта Button. С помощью обыч- обычного HTML-синтаксиса кнопка определяется так: < INPUT TYPE = "button I submit I reset" [ЖМЕ = " objectName" ] [VALUE = "labelText"] |[CnCliok = " methodtiame" ] > Эти три типа кнопок предназначены для различных целей: Кнопка Submit отправляет форму, в которой она со- содержится, на сервер, основываясь на параметрах формы. Для такого действия не нужен JavaScript- код, поскольку все поведение встроено непосред- непосредственно в объект. Кнопка Reset сбрасывает значения полей в теку- текущей форме, восстанавливая ранее установленные значения по умолчанию. Как и для кнопки Submit, JavaScript-код здесь не используется. Объект Button — это универсальный объект без предварительно определенного встроенного поведе- поведения. При работе с этим объектом необходимо добав- добавлять к кнопке обработчик событий onClick.
Использование DOM Часть III При недостаточном знакомстве с HTML может воз- возникнуть вопрос о целесообразности существования кно- кнопок Submit и Reset, т.к. объект Button можно использо- использовать для выполнения тех же самых задач. Они возникли до появления JavaScript, когда нельзя было использо- использовать универсальную кнопку, потому что не существо- существовало соответствующих способов. Кроме того, несмотря на то, что не все браузеры поддерживают JavaScript (a, значит, и объект Button), все современные браузеры поддерживают кнопки Submit и Reset. Преследуя цели совместимости, обычно лучше всего использовать кноп- кнопки Submit и Reset, если поддержка JavaScript не являет- является требованием для доступа к данной странице. При на- наличии таких требований выбор кнопок роли не играет. Для получения дополнительной информации о событии onClick для объектов типа Button стоит обратиться в главу 14. Листинг 17.6 демонстрирует пример использования всех трех кнопок. Как и следовало ожидать, кнопки Submit и Reset используются для отправки и очистки формы, хотя их параметры VALUE= были изменены для отображения более дружественных к пользователю формулировок. Объект Button используется для выво- вывода на экран справочного окна, которое подсказывает пользователю, как заполнять регистрационную форму. Вдобавок, в справочном окне (которое было сгене- сгенерировано методом showHelpQ) объект Button определя- определяется с помощью метода writeQ документа. Обратите вни- внимание на две вещи, связанные с этой кнопкой. Во-первых, для центрирования кнопки на странице ис- используется дескриптор <DIVALIGN=>. Во вторых, для увеличения ширины кнопки добавлено несколько про- пробелов до и после ОК в параметре VALUE=. На рис. 17.5 показана форма, сгенерированная в HTML. Листинг 17.6. buttons.htm. <html> <head> <titleX>nline Registration</title> <SCRIFT LANGOAGE="JavaScript"> function showHelpO { helpWin = window.open("", "Help", "height=200,width=400") helpWin. document.write ("<bodyXh2>Help on Registration</h2>") helpWin. document, write(. Please enter your product information into the fields. <p>") helpWin.document.write(. Press the Register button to submit your form.<p>") helpWin.document.write(. Press the Clear button to clear the form and start again.<p>") helpWin.document.write("<p>") helpWin. document. write ("<f ormXDIV ALIGN =' CENTER' >" > helpWin.document.write("<input type=button value=' OK 'onClick='window.closed '>") helpWin. document. write ("</DIVX/f ormX/body>") i </SCRIPT> </head> <body> <hl>Online Registration</hl> <form method="POST"> <p>Please provide the following product information: </p> <blockquote> <preXem> Product name </emXinput type=text size=25 maxlength=256 name="ProductName"> <em> Model </emXinput type=text size=25 maxlength=256 name="Product_Model"> <em> Version number </emXinput type=text size=25 maxlength=256 name="Product_VersionNumber"> <em>Operating system </emxinput type=text size=25 maxlength=2 5 6 name="Product_OperatingSystem"> <em> Serial number </emXinput type=text size=25 maxlength=2S6 name="Product_SerialNumber"> </pre> </blockquote> <pXinput type=submit value="Register"> <input type=reset value="Clear"> <input type=button -walue="Help" onClick="showHelp () "X/p> </form> </body
Объекты Form Online Regi! Rease provide BierallcrMn Pruauet п-bw VucaXca audit! »j»«i"T en:** (Пи! nw**f Help on Registration ¦nteryour product information into the nelds. 2 Press the Register buttnWo submit yOur form 3. Pee: г trie Clear button to dear (tie form and start agari. ay - Jig РИСУНОК 17.5. В этом приложении используются кнопки Button (OK), Reset (Clear) u Submit (Register). ПРИМЕЧАНИЕ Для увеличения эффективности при применении JavaScript 1.4 не следует определять имя функции, если используются массивы аргументов. В JavaScript 1.4 массив аргументов является не свойством объек- объектов Function, но переменной. Считайте, что функция, связывающая строки, как показано выше, имеет един- единственный аргумент, который содержит символы, раз- разделяющие составные элементы. function ConcatenateUnleashed (separator) { result="" // инициализация списка for (var i=l; Karguments.length; i++> { result += arguments [i] + separator } return result ] Функция просто создает списки, которые соответству- соответствуют передаваемым аргументами: // Возвращает "Ford; GM; Chrysler,-" ConcatenateUnleashed ("; " , "Ford" "GM" "Chrysler") O6beicrCheckbox Объект Checkbox — это тот же объект Form, но пред- предназначенный прежде всего для обозначения логических данных (true или false). Он действует как переключа- переключатель, который может быть включен или выключен поль- пользователем либо JavaScript-кодом. Для определения Checkbox используют следующий HTML-синтаксис: <INPUT TYPE="checkbox" [ NAME= " obj ec tName "] [VALUE="value" ] [CHECKED] [onClick="methodName" ]> laisplayText] Например, приведенный ниже код для флажка по- позволяет указывать, владеют ли пользователи иностран- иностранными языками: Глава 17 <input type=checkbox name="language">I speak multiple languages. Следующее соглашение для пользовательского ин- интерфейса связано с тем, что Checkbox не должен вызы- вызывать выполнение какого-либо действия (как это делают объекты Button). В результате его обработчик событий onClick, вероятно, будет применяться не столь широко. Исключением из этого правила является изменение со- состояния других объектов формы. ПРИМЕЧАНИЕ Дополнительная информация о событии onClick объекта Checkbox находится в главе 14. ¦ ¦ ¦ ¦.. Определение заполнения объекта Checkbox Возможно, наиболее важным свойством объекта Checkbox является свойство checked. Это свойство проверяется для определения, выставил ли пользователь флажок. Для проверки объекта Checkbox использовать свойство value нельзя и причины будут поясняться далее. ПРЕДОСТЁРЕИШЧИЕ Свойство value может поначалу вводить в заблужде- заблуждение. В отличие от некоторых сред, здесь свойство value статическое и в ответ на изменение состояния Checkbox не изменяется. Поэтому не проверяйте свойство value для определения факта выставления флажка. . - - . Для иллюстрации воспользуемся примером, приве- приведенным ранее при обсуждении объекта Text в этой гла- главе. В одном из примеров с помощью метода select() объекта Text при повторном вызове автоматически вы- выделялось содержимое объекта Text. Предположим, что для пользователей требуется создать опцию выделения/ невыделения текста. Для этого можно использовать фла- флажок. Листинг 17.7 содержит соответствующий код, а на рис. 17.6 показана результирующая форма. Листинг 17.7. checkboxSelect.htm. <html> <head> <title>Online Registration</title> <SCRIPT LANGOAGE="JavaScript"> function selectText (currentobject) (. if (document. f orml. selectBox. checked) { currentobject.select(} :i </SCRIPT> </head> <body> <form name="forml" method="POST"> <h2>Onllne Reglstratlon</h2>
Использование DOM Часть III <p>Username:<br> <input type=text size=25 maxlength=256 name="Username" onFocus="selectText (this) "Xbr> Browser used:<br> ¦<input. type=text size=25 maxlength=25G name="Browser" onFocus="seleotText(this)"><br> Email address :<strong> <br> </strongXinput type=text size=25 maxlength=256 name="EmailAddress" onFocus="selectText (this) "X/p> <h2xinput type=submit value="Register"> <input type=reset value="Clear"X/h2> <pXinput type=checkbox name="selectBox">Activate field selection. </form> </body> </html> Online Registration Uiurname P Adfcate Леи selection РИСУНОК 17.6. Использование флажка. ПРИМЕЧАНИЕ Пример, показанный в листинге 17.7, демонстрирует порядок вычисления отмеченного свойства. Однако, необходимо учитывать, что этот код не обязательно работает так, как ожидается. Как только выставлен флажок, текст будет выделяется от текущего пункта, независимо от того, снимет ли пользователь флажок. Так происходит потому, что при вызове метода select!) для объекта Text состояние выделения текста будет ос- оставаться в силе, пока страница не перезагрузится. Стоит заметить также, что при перегрузке страницы командой инструментальной панели "Reload" в Netscape Navigator содержимое формы сохраняется. В то же время, при использовании метода reload!) в Netscape Navigator 3.0 текущие значения в форме сбрасывают- Объект Radio Объект Radio используется для предоставления пользо- пользователям возможностей выбора одиночной опции из группы параметров. Если выбирается одна опция в пре- пределах набора, другие в тот же момент выбраны быть не могут. Щелчок на переключателе снимает выделение с любого другого выбранного ранее переключателя. Объект Radio отличается от других изученных ранее объектов Form. Заметим, что другие объекты Form име- имеют взаимно-однозначное соответствие HTML-дескрип- HTML-дескриптору, тогда как объекту Radio в пределах исходного HTML-кода соответствует целый набор элементов <INPUT type="radio">. Каждый элемент объекта Radio определяется таким образом: <INPUT TYPE="radio" [NAME="grroupWanie" ] [VALUE="value"] [CHECKED] IonClick="methodWame" ] > idisplayTextl Элементы здесь не группируются таким способом, как это делается с элементами в объекте Select (кото- (который обсуждается ниже в главе). Способ их группиров- группировки основан на параметре NAME= переключателя. Каж- Каждый элемент в объекте Radio должен использовать в этом параметре одно и то же значение. Например, сле- следующий набор переключателей работает с одним объек- объектом Radio — weekdays: <INPUT TYPE="radio" NAME="weekdays" VALUE="Monday">Monday ¦CINPUT TYPE="radio" NAME="weekdays" VALUE="Tuesday">Tuesday <INPUT TYPE="radio" NAME="weekdays" VALUE="Wednesday">Wednesday <INPOT TYPE="radio" NAME="weekdays" VALUE="Thursday">Thursday <INPUT TYPE="radio" NAME="weekdays" VALUE="Friday">Friday <INPUT TYPE="radio" NAME="weekdays" VALUE="Saturday">Saturday <INPUT TYPE="radio" NAME="weekdays" VALUE="Sunday">Sunday ПРИМЕЧАНИЕ За дополнительной информацией о событии опСНскдля объекта Radio обращайтесь в главу 14. Определение значения выбранного переключателя Одной из наиболее распространенных задач, которые должны решаться при использовании объекта Radio,, является проблема получения значения выбранного в данный момент переключателя. Для этого потребуется определить, какой из переключателей выбран и затем вернуть его значение. Вместо написания оригинально- оригинального кода каждый раз, проще воспользоваться универсаль- универсальной функцией, называемой getRadioVa!ue(), которая может возвращать значение объекта Radio, передаваемо- передаваемого в метод в качестве параметра.
Объект Form Рассмотрим код, показанный в листинге 17.8. Объект SongsRadio содержит список из трех песен. Объект Button "Show Selected" отображает выбранный в данный момент объект, вызывая метод getRadioValue() с пере- передачей объекта Songs в качестве параметра функции. Метод GetRadioValue() выполняет цикл for, предназна- предназначенный для проверки, какой из переключателей выбран. Для определения количества итераций используется свойство length объекта Radio. Когда цикл for сталки- сталкивается с выбранным значением, он присваивает пере- переменной значение переключателя, прерывает выполне- выполнение цикла, а затем возвращает значение в обработчик событий Button. Листинг 17.8. radio.htm. <html> <head> <script language = " JavaScript" > function getRadioValue(radioObject) var value = null for (var i=0; i<radioObject. length; { if <radioObject[i].checked) { value = radioObjectfi] .value break } } return value } </script> </head> <body> <?orm name="forml"> <pxinput type=radio name=" songs*1 value=" Liquid" >Liquid</p> <pxinput type=radio name=" songs" value="Flood">Flood</p> <pxinput type=radio name="songs" value="World' s Apart" >World' s Apart</p> <input type=button value="Show Selected" onClick="alert (getRadioValuefthis. form, songs) ) "> < / f orm> </body> </html> На рис. 17.7 показан результат нажатия кнопки "Show Selected". ПРИМЕЧАНИЕ Листинги 17.12 и 17.17, приведенные ниже в главе, демонстрируют способ автоматической проверки пе- переключателя. .... .... .... Объект Select Объект Select — один из наиболее полезных и гибких объектов Form. Его можно использовать в тех же слу- случаях, что и объект Radio. Объект Select нуждается в меньшем количестве реального пространства по сравне- сравнению с объектом Radio, которому необходимо простран- Глава17 ство под каждый переключатель. Базовый синтаксис HTML для объекта Select выглядит так: <SELECT [NAME="objectName"] [SIZE="numberVisible"] [MULTIPLE] [onBlur="methodNanie"] :[onChange="jnet.hodName"] [onFocus="jne thodName"]> <OPTION VALUE="optionValue" [ SELECTED ]>dispIayText</OPTION> [<OPTION VALUE=" optionValue">d±splayText </OPTION>] </SELECT> -"»»• sMUM ¦ i Г Liquid tfVrtirkb Apart РИСУНОК 17.7. Определение значения объекта Radio. Благодаря своей гибкости, объект Select может при- принимать три различных формы: список выбора, прокру- прокручиваемый список и прокручиваемый список с мульти- выбором. ПРИМЕЧАНИЕ Дополнительная информация о событиях объекта Select может быть найдена в главе 14. Создание списка выбора Список выбора — это выпадающий список опций, в котором пользователь может выбрать только одну оп- опцию. Список выбора обычно отображает одно значение на экране (см. рис. 17.8), но при нажатии на стрелку список расширяется и отображает все элементы выбора (см. рис. 17.9). В отличие от комбинированных списков Windows, вводить значение в список выбора не допус- допускается; можно только выбирать элемент из существую- существующего массива элементов. Список выбора, показанный на рис. 17.8 и 17.9, мож- можно определить так: <select NAME="songs" SIZE=1> <option VALUE="Liquid">Liquid</option>
Использование DOM Часть III <option VALOE="World's Apart">World" s Apart </option> <option VALUE="Ironic">Ironic</option> -Coption VALUE=979">1979</option> <option VALUE="Wonderwall">Wonderwall</option> <option VALUE="Standing Outside a Broken Phone wBooth">Standing Outside a Broken Phone Booth</option> РИСУНОК 17.8. Список выбора в начальном состоянии. РИСУНОК 17.9. Список выбора вразвернутом состоянии. Ключ к определению списка выбора заключается в присвоении параметру SIZE значения 1 (либо вообще никакого значения). Это даст гарантию того, что спи- список будет отображать только одну строку. Создание прокручиваемого списка Второй формой объекта Select является прокручивае- прокручиваемый список, во многих средах называемый окном спис- списка. Он отображает указанное число элементов одновре- одновременно в формате списка, вместо того чтобы прятать все элементы кроме одного, как это делает выпадающий список. Прокручиваемый список включает полосу про- прокрутки, при этом пользователь может прокручивать спи- список элементов вверх или вниз, чтобы просматривать и те элементы, которые не уместились в окне. ¦ Для создания прокручиваемого списка единственное изменение в HTML-определении <select> необходимо проделать в параметре SIZE=. Если его значение боль- больше 1, объект Select преобразуется в прокручиваемый список. Например, если изменить параметр SIZE= оп- определенного ранее объекта Songs с 1 на 5, список при- примет новый вид, показанный на рис. 17.10. Как и спи- список выбора, прокручиваемый список позволяет выбирать только одно значение. Создание прокручиваемого списка с мультивыбором Последняя форма, в которой может быть представлен объект Select, — это прокручиваемый список с мульти- мультивыбором. Он выглядит так же, как обычный прокручива- прокручиваемый список, но ведет себя по-другому. Из этой формы объекта Select можно выбирать один и более элементов. Решение задачи выбора множества элементов шсит от среды. В большинстве случаев можно либо перемешать мышь с нажатой кнопкой поверх требуемых элементов, либо удерживать в нажатом состоянии к шу Shift или Ctrl во время щелчков на элементах списка. РИСУНОК 17.10. Прокручиваемый список. Для определения прокручиваемого списка с мульти- мультивыбором необходимо в определение объекта Select до- добавить параметр MULTIPLE: <select NMJE=" songs" SIZE=5 MOLTIPLE> <option VALUE="Liquid">Liquid</option <option VALUE="World' s Apart">World'» Apart </option> <option VALUE="Ironic">Ironic</option> <option VALUE=979">1979</option> <option VALOE="Wonderwall">Wonderwall</option>
Объекты Form <option VALUE="Standing Outside a Broken Phone "¦¦Booth" > .Standing Outside a Broken Phone Booth</option> Определение значения или текста выбранной опции В списке выбора или прокручиваемом списке можно определять значение выбранной опции с помощью ком- комбинации свойств options и selectedlndex объекта Select. Например, если требуется определить песню, которая была выбрана в приведенном выше примере объекта Songs, используют следующий код: favorite = document.forml.songs.options I [document.forml.songs.selectedlndex].value Свойство options — это массив, содержащий каждую опцию, определенную внутри объекта Select. Исполь- Используя это свойство, можно обращаться к свойствам каж- каждой опции. С помощью свойства Selectedlndex возвра- возвращается индекс выбранной опции. Когда options и Selectedlndex используются в комбинации, возвращает- возвращается значение выбранной в данный момент опции. С учетом требований точечной нотации JavaScript, выбранное в данный момент значение может включать длинные строки текста программы. Этого можно избежать с помощью универсального метода getSelectValue(). Ли- Листинг 17.9 показывает способ применения такого мето- метода. Как видно из листинга, объект Select переходит к параметру метода getSeIectValue(), как только пользо- пользователь нажимает на кнопку "Show Current". Переменная SelectObject обрабатывается как переменная объектно- объектного типа и принимает значение выбранной в данный момент опции. Это значение переходит в обработчик событий объекта Button и отображается в сигнальном окне сообщения. Листинг 17.9. select.htm. <html> <head> <script language = "JavaScript"> function getSelectValue(selectObject) { return selectObject. options[selectObject.selectedlndex]. value </script> </head> <body> <form name="forml"> Songs: <select NAME="songs" SIZE=1> <option VALUE="Liquid">Liquid</option> <option VALUE="World's Apart">World's Apart </option> <option VALUE="Ironic">Ironic</option> <option VALUE=979">1979</option> <option VALUE="Wonderwall">Wonderwall</option> <option VALUE="Standing Outside a Broken Phone Глава 17 Standing Outside a Broken Phone Booth</option> </SELECTXp> <input type=button value="Show Current" onClick="alert(getSelectValue(this.form.songs))"> </form> </body> </html> Одно важное различие между объектами Select и Radio связано с тем, что объект Select, в дополнение к свойству value, имеет свойство text. Если определяемое значение аналогично тому, которое отображается для пользователя (как в листинге 17.9), то можно вместо свойства value возвращать значение text выбранного в данный момент объекта. Предположим, что объект Select был определен так: <select NAME="songs" SIZE=1> <option>Liquid</option> <option>World's Apart</option> <option>Ironic</option> ¦<option>197 9</option> <option>Wonderwall</option> <option>Standing Outside a Broken Phone Booth </option> Тогда для возврата названия песни вместо свойства value можно воспользоваться свойством text: function getSelectValue(selectObject) { return selectObject.options[selectObject. selectedlndex].text Определение значений в прокручиваемых списках с мультивыбором В списках, где в каждый момент времени может быть выбрана только один вариант, свойство selectedlndex работает эффективно и возвращает необходимую ин- информацию из выбранной опции. Однако, в прокручи- прокручиваемом списке с мультивыбором selectedlndex возвраща- возвращает только первую выделенную опцию, а не все сразу. При использовании списка с мультивыбором необхо- необходимо применять свойство selected массива опций для определения состояния каждой опции в списке. Ли- Листинг 17.10 демонстрирует пример этого в методе showSelection(). Цикл for выполняет итерации по каж- каждой опции объекта Select и проверяет, равно ли свой- свойство selected значению true. Если да, то значение свой- свойства text элемента добавляется в переменную списка. Результат отображается во втором окне, показанном на рис. 17.11. Листинг 17.10. selectMultiple.htm. <html> <head> <script language = "JavaScript"> function showSelection(objectName)
Использование DOM Часть III var list = for (var i=0; i<objectName. length; if (objectName. options [i] . ^selected) { list += objectName.options[i].text + "<p>" selWindow = window. open ( " " , "Selections", "height=200,width=400") selWindow.document.write("<h2>You ^•picked the following songs : </h2XpXp>") selWindow.document.write(list) </script> </head> <body> <form name="forml"> Pick Youx Favorite Songs From the List:<p> <select NAME="songs" SIZE=5 MULTIPLE> <option>Fortress Around Your Heart</option> <option>Breakf ast at Tiffany' s</option> <option>Flood</option> <option>The Chess Game< <option>Liquid</option> <option>World's Apart</option> <option>Ironic</option> <option>1979</option> <option>Wonderwall</option> <option>Standing Outside a Broken Phone Booth </option> </SELECTXp> <input type=button value="Show Selection" onClick="showSelection(this.form.songs)"> </form> </body> </html> <body> <form name="forml"> Favorite Band: <input type=text name=" size=20 onBlur="quickSelect () "Xp> Songs: <select NAME="songs" SIZE=1> <option VALUE="Liquid">Liquid</option> <option VALUE="World's Apart">WorId's Apart </option> <option VALOE="Ironic">Ironi c</option> <option VALUE=979">1979</option> <option VALUE="Wonderwall">Wonderwall</option> <option VALUE="Standing Outside a Broken Phone *»Booth"> Standing Outside a Broken Phone Booth</option> </SELECTXp> <input type=button value="Show Current" onClick="quickSelect()"> </form> </body> </html> - IWtt'fcail^W.h ,1-1 l^-F.J... f"iiv " " Выбор опции с помощью JavaScript Можно программно выбирать опцию, устанавливая свойство selected массива параметров объекта Select. Предположим, что имеется поле "Favorite Band" и спи- список песен. Пусть значение поля "Favorite Band" — Oasis, и требуется расположить песню, исполняемую этой группой, в поле "Songs". В листинге 17.11 показан код этого примера. Листинг 17.11. selectSelected.htm. <html> <head> <script language = "JavaScript"> function quickSelect() { var bnd = с bnd = bnd.toUpperCase() if (bnd = "OASIS") { document.forml.songs[4].selected = " </script> </head> P ИСУ Н О К17.11. Отображение множественного выбора. Объект Password Как можно понять по его имени, объект Password пре- преследует одну цель: захватывать значения пароля, вве- введенного пользователем. Объект Password аналогичен объекту Text, но отображает любой символ, напечатан- напечатанный пользователем в поле, в виде звездочки (*). Этот объект определяется в синтаксисе HTML следующим образом: <INPUT TYPE= "pas sword" [NAME=" objectName"] [VALUE="defaultPassword"J [SIZE=integer] > Ниже приведен пример: <INPUT TYPE="password" NAME="passwordField" SIZE=15> JavaScript не предоставляет большой степени управ- управления объектом Password. Например, нет возможности
Объекты Form получать значение текста, введенного пользователем; можно только получить заданный по умолчанию текст, который был определен в параметре VALUE= дескрип- дескриптора <INPUT type=Password>. Одна из причин, почему JavaScript не может получить доступ к объекту Password, связана с тем, что JavaScript-код в настоящее время встраивается в HTML-документ так, чтобы пользователь мог обращаться к нему. Когда язык JavaScript будет разработан до конца, вероятно, появится большая сте- степень управления этим объектом. Объект Hidden Как можно понять по его имени, объект Hidden неви- невидим для пользователя. Объект Hidden — это поле скры- скрытого текста, использующееся для хранения значений, которые не требуется представлять пользователю в обычных текстовых полях. Затем можно передавать эту информацию на сервер для обработки. Объект Hidden в HTML определяется с помощью следующего синтак- синтаксиса: TYPE="hidden" MAME="objectName" [VALUE= "value" ] > Листинг 17.12. hidden.htm. Глава 17 Ниже приведен пример: <INPUT TYPE="hidden" NAME="hiddenFieldl"> В HTML-мире скрытые поля играли важную роль в получении определенной информации со стороны пользователя, которая затем использовалась сервером. С появлением JavaScript, применение объекта Hidden в комбинации с JavaScript становится менее эффектив- эффективным. Причина связана с тем, что глобальные перемен- переменные JavaScript служат тем же целям, что и объекты Hidden, однако ими намного проще управлять. Следующие два примера демонстрируют это. На рис. 17.12 показан набор переключателей, на которых мож- можно совершать щелчки. Необходимо добавить код к кноп- кнопке "Undo Last", чтобы пользователь мог отменять пос- последний сделанный выбор. Использовать кнопку Reset для этого нельзя, т.к. она или сбросит все переключа- переключатели, или вернет значение по умолчанию. Вместо этого для выполнения упомянутой задачи придется добавить JavaScript-код. Код, приведенный в листингах 17.12 и 17.13, демонстрирует решение такой задачи. Листинг 17.12 использует для этого набор скрытых полей, в то время как листинг 17.13 выполняет данную задачу с по- помощью глобальных переменных. Заметим, что оба эти метода — вполне допустимы. <html> <head> <title>Hidden Test</title> ¦< script language="JavaScript"> function postData(value) { document.forml.holder2.value = document.forml.holder.value document.forml.holder.value = value function resetValue(> ( var len = document.forml.ctyList.length ;for (var i=0; i<len; i++) { if (document.forml.ctyList[i].value =s document.forml.ctyList[i].checked break } document.forml.holder2.value) { " </script> </head> <body> <hl>I remember</hl> <form name="forml" method="POST"> <pXinput type=radio name="ctyList" value="Argentina" onClick="postData (this.value)">Argentina</p> <pXinput type=radio name="ctyList" value=" Burkina Faso" onClick="postData(this.value)">Burkina Faso</p> <p><input type=radio name="ctyList" value="Pakistan" onClick="postData(this.value)">Pakistan</p> <p><input type=radio name="ctyList" value="Switzerland" onClick="postData(this.value)">Switzerland</p> <pXinput type=radio name=" ctyList" value="United Kingdom" onClick="postData (this, value) "MJnited Kingdom</p> <pXinput type=radio name="ctyList" value="United States of America"
Использование DOM Часть III onClick="postData(this.value>">United States of America</p> <pXinput type=radio name="otyList" value="Zambia" onClick="postData (this .value) ">Zaitibia</p> <pxinput type=radio name="ctyList" value="Zimbabwe" onClick="postData(this.value)">Zimbabwe</p> <pxinput type=button name="UndoLast" value="Undo Last" onClick="resetValue () "X/p> <INPUT TYPE="hidden" NAME="bolder" value="'"> <INPUT TYPE="hiddenlr NAME="holder2" value=""> </form> </body> </html> Листинг 17.13. hiddenVars.htm. <html> ¦<head> <title>Hidden Var Test</title> <script language^"JavaScript"> var holder = "" var holder2 = "" function postData (value) { holder2 = holder holder = value ) function resetValue() ( var len = document.forml.ctyList.length for (var i=0; i<len; i++) { if (document.forml.ctyList[i].value = holder2) document.?orml.ctyList[i].checked = " break ) </script> </head> <body> <hl>I remember</hl> <form name="forml" method="POST"> <pXinput type=radio name="ctyList" value="Argentina" onClick="postData(this.value)">Argentina</p> <pxinput type=radio name="ctyList" value="Burkina Faso" onClick="postData(this.value)">Burkina Faso</p> ¦<pxinput type=radio name="ctyList" value="Pakistan" onClick="postData(this.value)">Pakistan</p> <pXinput type=radio name="ctyList" value="Switzerland" onClick="postData(this.value)">Switzerland</p> <pXinput type=radio name="ctyList" value="Onited Kingdom" onClick="postData(this.value)">United Kingdom</p> <pXinput type=radio name="ctyList" value="United States of America" onClick="postData(this.value)">United States of America</p> <p><input type=radio name="ctyList" value="Zambia" onClick="postData(this.value)">Zambia</p> <pxinput type=radio name="ctyList" value="Zimbabwe" onClick="postData(this.value)">Zimbabwe</p> <pXinput type=button name="UndoLast" value="Undo Last" onClick="resetValue () "X/p>- '</form> </body> </html> В последнем примере всякий раз, когда пользователь нем holder, а текущее значение holder — в объект holder2. щелкает на переключателе, метод postData() помещает Это значение затем используется, когда пользователь текущее значение переключателя в объект Hidden с име- нажимает на кнопку "Undo Last", в результате чего вы- выбирается соответствующий переключатель.
Объекты Form I remember РИСУНОК П.12. Сохранение последнего значения с помощью объекта Hidden. Глава 17 Во втором примере переменные holder и hol(ler2 определены глобально в начале сценария. Сценарий использует эти переменные вместо ссылок на объекты Hidden. Резюме Формы играют важную роль в JavaScript. Помимо того, что появляется возможность классифицировать и обра- обрабатывать данные до их отправки на сервер, HTML-фор- HTML-формы можно также использовать для создания клиентских приложений, использующих JavaScript. В этой главе рассматривался объект Form и различные объекты, ко- которые могут существовать внутри него. Кроме того, были показаны способы отправки формы на сервер и методы работы и проверки значений введенных данных до от- отправки данных на сервер.
Объекты Frame В ЭТОЙ ГЛАВЕ Объект Frame Объект Location Объясг History Объект Navigator В этой главе обсуждается объект Frame и огромное число его применений при создании Web-сайтов. Для начала стоит рассмотреть создание одиночных и муль- тифреймовых окон и связанные с ними методы, свой- свойства и события. Затем можно перейти к распространен- распространенным объектам, таким как объекты Navigator и History. Их предшественник — это, конечно же, известный ре- позитарий для регистрации пользовательских взаи- взаимодействий и адресов посещенных страниц, который по- позволяет получать информацию касательно текущего браузера. Эта глава может показаться достаточно длин- длинной, однако, следует помнить, что она и должна содер- содержать большое количество необходимых разделов, посвя- посвященных фреймам и окнам. Объект Frame Фреймы были введены еще в Netscape Navigator 2.0. Фрейм (frame) — это подокно полного окна браузера; его спецификации определяются разработчиком. Фреймы очень быстро обрели популярность, поскольку они по- позволяют одновременно в одном и том же окне отобра- отображать сразу несколько документов. Каждый фрейм может содержать отдельный документ (HTML, текст, изображение и пр.), каждый фрейм име- имеет свой адрес и полосу прокрутки. Как и в случае оди- одиночных окон, фреймы можно вызывать и ссылаться на них. Можно также загружать документы во фреймы без воздействия на документы в других фреймах. Фреймы обеспечивают средства просмотра и вза- взаимодействия с сайтом, который не доступен другим способом. Они позволяют постоянно отображать нави- навигационное подокно, которое обеспечивает быстрый и эффективный поиск требуемых страниц сайта. Можно> одновременно отображать входные и выходные формы, а также просматривать большое количество документов одновременно. Можно выбирать для просмотра различ- различные файлы изображений, используя меню. Для отобра- отображения расширенного вида документа можно открывать новое окно, которое будет закрываться, когда оно боль- больше не нужно. Фреймы также обеспечивают возможность слайдовой демонстрации. Использование и реализация мультифреймового сайта ограничены только воображе- воображением его автора. Например, окно могло бы содержать несколько про- прокручиваемых фреймов, которые указывают на некоторые URL, которые, в свою очередь, могут указывать на фрей- фреймы. Объекты Frame создаются с помощью дескрипторов <FRAME> внутри дескрипторов <FRAMESET>, и они будут, по сути, объектами Window, от которых и унасле- унаследуют все методы и свойства. Для получения дополнитель- дополнительной информации относительно этих методов, свойств и ¦общего поведения можно обратиться в главу 15. ; ПРЕДУПРЕЖДЕНИЕ, ^^¦^, . t . ; \ /X Некоторые посетители сайтов считают фреймы и но- новые окна в определенной степени отвлекающими. К тому же, иногда при использовании фреймовой структуры информация покидает область отображе- отображения, особенно в случае маленького монитора. Авто- Автору сайта необходимо удостовериться, что использо- использование фреймов удобно для посетителей; желательно также предусмотреть доступ к альтернативной не- нефреймовой версии сайта. JavaScript существенно расширяет возможности сай- сайта с фреймами и многое добавляет в способы взаимодей- взаимодействия сайта с пользователями. Можно программно от- открывать и закрывать новые окна. Можно обновлять и синхронизировать фреймы с помощью сценария без уча- участия серверной программы. Карты изображений и ссыл- ссылки могут быть динамическими, т.е. изменяющимися в
Объекты Frame зависимости от различных конфигураций и применений сайта. Документы в различных фреймах и окнах могут взаимодействовать друг с другом и передавать друг дру- другу информацию. Сетевые ресурсы, касающиеся JavaScript и фреймов, находятся на сайте Netscape по адресу http: / / home.netscape.com /. Реальная выгода фреймов заключается в возможно- возможности обеспечивать постоянное навигационное меню сай- сайта. Вместо прыжков с одной страницы на другую пользо- пользователь может выбрать страницу из меню, и она появится в другом (главном) фрейме. Оглавление может отобра- отображаться в одном фрейме, а документы — в другом. Можно разместить фрейм с кнопочной панелью с одной сторо- стороны окна, и в этом фрейме пользователь будет нажимать на кнопки, если ему потребуется загрузить часть сайта в отображающий фрейм. * совет -;;._ . . ; "ti. . :, ' .-ч -; ч,- - .;" Использование фреймов имеет и некоторые недостат- недостатки. Главный недостаток связан с уменьшением обла- области отображения каждого документа. Пользователям с небольшими мониторами, портативными или карман- карманными компьютерами будет сложно в подробностях рассмотреть некоторые документы в фреймах. Непло- Неплохим выходом может оказаться создание наряду с фрей- фреймовой также и нефреймовой версии сайта и предос- предоставление всем пользователям возможности просмотра выбранной версии (с помощью JavaScript это сделать довольно-таки просто). Объект Frame, по сути, аналогичен объекту Window, и с ним работают подобными же методами. В случае одиночного окна объект Window представляет собой объект самого высокого уровня. В случае фреймов окно самого высокого уровня считается родительским, а его дочерние окна считаются объектами Frame. Создание фреймов Фреймы создаются с помощью дескрипторов <FRAMESET> и определяются дескрипторами <FRAME>. <HTML> <HEAD> <TITLE>Creating ?rames</TITLE> </HEAD> <FRAMESET COLS=0%,*,5%"> <FRAME SRC="docl.html" NftME="framel"> <FRAME SRC=" doc2.html" NAME="frame2"> <FRAME SRC="doc3.html" NAME="frame3"> </FRBMESET> </HTML> За счет добавления нескольких строк кода можно легко создать окно с тремя фреймами: <HTML> Глава 18 <НЕМ» <TiTLE>Window frames: Window One</TITLE> </НЕМ» <FRSMESET ROWS=5%,45%" COLS=0%,60%" onLoad="alert('Windows have frames')"> <FRBME SRC="docl.htnil" NftME="framel"> <FRAME SRC="doc2,html" NftME="frame2"> <FRftME SRC="doc3.html" NMffi="frame3"> <FRaME SRC="doc4.html" NSME="frame4"> </FRftMESET> </HTML> (Выравнивание дескрипторов <FRAME> не является необходимым, но часто делается с целью обеспече- обеспечения лучшего вида программы и для демонстрации мерархии фреймов в коде. Некоторые HTML-редак- HTML-редакторы выравнивают дескрипторы автоматически, они могут также окрашивать некоторые фрагменты кода для лучшей читаемости. Дескрипторы <FRAMESET> Дескриптор <FRAMESET> имеет атрибут для описания способа разделения окна на фреймы. Этим атрибутом может быть COLS или ROWS (для столбцов или строк), но не оба сразу. Разработчик определяет количество строк или столбцов фреймов в окне и размеры каждого фрейма. Для каждой строки или столбца может опреде- определятся либо абсолютный размер в пикселах, либо отно- относительный размер в процентах от окна, либо размер вычисляется как остаток от окна после установки дру- других фреймов. Следующая строка создает два фрейма в виде столбцов, один размером 60% от окна, а другой — в оставшейся части окна (указан с помощью "*", в дан- данном случае этот размер составляет 40%): <FRAMESET COLS=0%,*"> 'Следующая строка кода создает снова два фрейма, но без использования знака процента. Абсолютная шири- ширина первого фрейма — 60 пикселов: <FRRMESET COLS=0,*"> Как и прежде, второй фрейм создается в оставшейся части окна. Следующая строка создает четыре фрейма в виде столбцов; три фрейма занимают по 30% ширины экра- экрана каждый, а четвертый — оставшуюся часть: <FRftMESET COLS=0%,30%,30%,*"> В данном случае можно заменить знак "*" на 0%". Для последнего фрейма использовать "*" необязательно. Однако, если размеры всех фреймов определяются че- через проценты, в сумме они должны составлять 100% ширины окна. Следующая строка кода создает два фрейма в виде строк, первый размером 70% высоты окна, а второй — 30%: <FRAMESET ROWS=0%,30%">
Использование DOM Часть III Размеры фрейма можно задавать с помощью сочета- сочетания абсолютных, относительных размеров и остатка, но если полный размер всех фреймов не равен размеру окна, результаты будут непредсказуемыми. Указание размеров фреймов только с помощью символа "*" могло ¦бы показаться очевидным; однако, "*" можно использо- использовать для каждого фрейма. Следующая строка создает три равных фрейма, каждый размерами в треть высоты окна: <FRAMESET ROWS="*,*,*"> Дескрипторы <FRAME> Атрибуты дескриптора <FRAME> определяют доку- документ, который будет загружаться в фрейм, имя фрей- фрейма, границы фрейма, полосу прокрутки и опции изме- изменения размеров. Все следующие атрибуты дескриптора <FRAME> — необязательны: Атрибут SRC — URL (относительный или абсолют- абсолютный) документа, который будет загружаться во фрейм. Документ может быть получен с того же сер- сервера в виде фреймового файла или с другого серве- сервера. Если атрибут SRC не используется, фрейм будет пустым. Это пустое пространство можно заполнить чем угодно, особенно, если для записи содержимого в фрейм воспользоваться JavaScript. Атрибут NAME, если определен, обеспечивает сред- средства для ссылки на фрейм из другого фрейма, а так- также из JavaScript. JavaScript может также ссылаться на фрейм через массив frames, который рассматривает- рассматривается далее в главе. Значение атрибута NAME должно начинаться с алфавитно-цифрового символа. Границы фрейма устанавливаются с помощью двух атрибутов, MARGINWIDTH и MARGINHEIGHT: Атрибут MARGINWIDTH управляет боковыми границами фрейма. Этот атрибут может прини- принимать значение в пикселах, начиная с единицы. Максимальное значение ограничено только разме- размером фрейма. (Невозможно установить границы таким образом, чтобы не осталось места для ото- отображения документа.) Атрибут MARGINHEIGHT аналогичен MARGINWIDTH за исключением того, что он управляет верхней и нижней границами. Если не указаны значения MARGINWIDTH и MARGINHEIGHT, браузер выбирает для них значения по умолчанию. Атрибут SCROLLING определяет полосу прокрут- прокрутки для фрейма. Значениями для SCROLLING мо- могут быть YES, NO и AUTO. YES означает, что по- полоса прокрутки всегда присутствует в фрейме. NO означает, что полоса прокрутки не отображается. AUTO отображает полосу прокрутки только, если документ по размерам превышает фрейм. Значение по умолчанию для SCROLLING — AUTO. • NORESIZE запрещает пользователю изменять раз- размеры фрейма. Для этого атрибута значение не ука- указывается. По умолчанию, если этот атрибут не оп- определен, весь фрейм получит изменяемые размеры. Изменять размеры фреймов, которые имеют атрибут NORESIZE, нельзя. •^СОВЕТ . г Если это возможно, лучше не определять этот атри- атрибут, т.е. разрешить пользователю изменять размеры фрейма. ¦Следующий фрагмент кода присваивает фрейму имя framel, загружает документ, устанавливает боковые границы в 5 пикселов, верхние и нижние границы в 10 пикселов, всегда отображает полосу прокрутки и не раз- разрешает изменять размеры фрейма: < FRMJE SRC = "docl.html" NAME = "framel" MARGINWIDTH=S MARGINHEIGHT=10 SCROLLING =YES NORESIZE> Netscape и Microsoft предоставляют расширенные возможности в браузерах последних версий. Посетите web-сайты этих компаний, на которых находится более подробная информация (соответственно http:// home.netscape.com/ и http://www.microsoft.com/). При использовании фреймов дополнительно не- необходимо рассмотреть обработку событий, отлаживая JavaScript-код или подстраивая его под целевой браузер. JavaScript-события, наиболее часто встречаемые как в Microsoft Explorer, так и в Netscape Navigator, сведены в табл. 18.1. Размещение дескрипторов Дескрипторы <FRAMESET> и <FRAME> обычно раз- размещают в теле документа. Однако, в некоторых версиях Netscape Navigator помещение их между дескрипторами <BODY> и </BODY> не позволяет браузеру прочесть дескрипторы <FRAMESET>. Поскольку дескрипторы <BODY> необязательны, дескрипторы <FRAMESET> размещают после раздела <HEAD> документа, а деск- дескрипторы <BODY> опускают, как показано ниже: <нтмь> <НЕМ» <TITLE>Frame Demo</TITLE> </HEAD> <FRAMESET COLS=0%,*"> <FRAME SRC="docl.html" KAME="framel"> <FRAME SRC="doc2.html" NAME="frame2"> </FRAMESET> </HTML>
Таблица 18.1. Объект JavaScript-события и фреймы. Событие Описание иьъекты trame EW3 Глава 18 ЁШ Окно или фрейм <BODY> <FRAMESET> <FRAME> dragdrop error focus load Move Resize unload Пользователь выбрал объект в окне. Окно загружено с ошибкой. Окно получило фокус. Окно загружено. Окно было перемещено. Окно было изменено. Пользователь покинул окно. Этот код устанавливает фреймы и загружает соответ- соответствующие документы. Фактически, можно сделать файл меньше, поскольку дескрипторы <HTML>, <HEAD> и <BODY> необязательны; файл может содержать только дескрипторы <ТПЪЕ>, <FRAMESET>h <FRAME>, как показано в следующем фрагменте. (Открывающий и закрывающий дескрипторы <TITLE> — единственные дескрипторы, которые по требованиям спецификации HTML должны присутствовать в каждом HTML-доку- HTML-документе.) <TITLE>Frame Demo</TITLE> <FRftMESET COLS=0%,*"> <FRRME SRC=" docl.html" NAME="framel"> <FRRME SRC="doc2.html" NAME="frame2"> </FRAMESET> Дескриптор <NOFRAMES> Многие авторы устанавливают также дескрипторы <NOFRAMES> для отображения сообщений в браузе- браузерах, не использующих фреймы: <NOFRAMES> код и текстовое содержимое для отображения в ¦браузерах, не поддерживающих фреймы </NOFRRMES> Содержимое может включать в себя как HTML-дес- HTML-дескрипторы, так и текст. Поддерживающий фреймы браузер игнорирует информацию между дескрипто- дескрипторами <NOFRAMES> и </NOFRAMES>, тогда как браузер, не поддерживающий фреймы, игнорирует <FRAMESET>, <FRAME> и <NOFRAMES>, но ото- отображает информацию, находящуюся между дескрипто- дескрипторами <NOFRAMES>h </NOFRAMES>. Дескрипторы <NOFRAMES> размещают внутри дескрипторов <FRAMESET>: <TITLE>Frame Demo</TITLE> <FRAMESET COLS=0%,*"> <FRAME SRC="docl.html" NAME="framel"> <FRAME SRC=" doc2.html" NftME="frame2"> <NOFRAMES>- код и текстовое содержимое дпя отображения в браузерах, не поддерживающих фреймы </NOFRAMES> </FRAMESET> Некоторые разработчики фактически дублируют глав- главный документ сайта внутри дескрипторов <NOFRAMES> для безфреймовой версии. Однако, обычно нет не- необходимости использовать подобную методику, т.к. с помощью JavaScript можно создавать фреймовую версию сайта для тех же самых страниц, которые ото- отображаются в браузерах, не поддерживающих фрей- фреймы. Интересно отметить, что дескрипторы <BODY> мож- можно заключать в дескрипторы <NOFRAMES>, исполь- используя атрибуты background, bgcolor, text и т.п. для без- безфреймовой версии документа. Браузер, не поддерживающий фреймы, игнорирует <FRAMESET> и начинает выполнять раздел <BODY> с первого изве- известного ему дескриптора (т.е. с дескриптора <BODY>) внутри дескрипторов <NOFRAMES>. Поддерживаю- Поддерживающий фреймы браузер инициализирует раздел <BODY> в первом дескрипторе <FRAMESET> и игнорирует со- содержимое дескриптора <NOFRAMES>. Конечно, под- поддерживающий фреймы браузер загружает документы, указанные дескрипторами <FRAME>, следовательно дескрипторы <BODY> этих документов таким браузером распознаются. Вложенные фреймы Можно создавать вложенные фреймы, в которых фрейм будет разделен еще на несколько других фреймов. Су- Существует два разных способа создания вложенных фрей- фреймов, оба они обеспечивают похожие результаты. Одна- Однако, возникает различие в иерархии фреймов и в способах ссылок на вложенные фреймы. Следующий код создает фреймы с мультифреймовой структурой в одном родительском окне. На рис. 18.1 показаны фреймы, а на рис. 18.2 — структура (иерархия) этих фреймов. <FRMffiSET COLS=0%,*"> <FRftME SRC="docl.html" NftME="framel">
Использование DOM Часть III <FRftMESET ROWS="*,20%"> <FRftME SRC="doc2.html" NftME="?rame2"> <FRW4E SRC="doc3.html" NAME="?raine3"> </FR»MESET> </FRAMESET> В коде для рис. 18.2 все три фрейма — дочерние фрей- фреймы одного и того же верхнего окна. В коде, создающем фреймы на рис. 18.4, только для фреймов framel и frame2 родительским окном является верхнее окно, a frame3 и frame4 — это дочерние фреймы окна frame2. По этой причине ссьшаться на данные фреймы необходимо по- разному, и эти различия будут рассматриваться в следу- следующих разделах. РИСУНОК 18.1. Создание мулыпифреймовой структуры в одномродителъском окне. Top Window \ '¦;¦'¦'¦: ¦¦¦ ¦ _ Parent is fia : ;.< в . Г framel frame2 РИСУНОК 18.2. Иерархия фреймов в одном родительском окне. Следующий код создает фреймы с мультифреймовой структурой в двух окнах. (Фрейм тоже можно считать ок- окном.) На рис. 18.3 показаны эти фреймы, а на рис. 18.4 — их иерархия. <FRAMESET COLS=0%,*"> <FRAME SRC="docl.html" NAME=" framel "> <FRAME SRC="frame2.html" NAME="frame2"> </FRAMESET> Файл frame2.html содержит следующую дополни- дополнительную информацию для установки фреймов: <FRAMESET ROWS="*,20%"> <FRSME SRC="doo2.html" NAME="frame3"> <FRAME SRC="doc3 . html" !№ME="frame4"> </FRftMESET> Эти два фрагмента кодов создают фреймы, которые выглядят совершенно одинаково, как показано на рис. 18.1 и 18.3. Однако, структуры этих фреймов, как мож- можно заметить из рис. 18.2 и 18.4, — полностью различны. 5»s РИСУНОК 18.3. Создание фреймов с мулыпифреймовой структурой в двух окнах. TopWindow Г framel I frame 2 I Г frame3 I frame4 РИСУНОК 18.4. Иерархия фреймов с мультифреймовой структурой в двух окнах. Добавление JavaScript-кода ко фреймам Файлы с наборами фреймов и большинство файлов до- документов, которые отображаются в фреймах — это HTML-файлы. Таким образом, в них можно использо- использовать JavaScript, как это делалось в других HTML-фай- HTML-файлах. Единственное отличие связано с тем, что здесь JavaScript ссылается и на свойства других документов, находящихся в фреймах, а также использует определен- определенные особенности ссылок на эти свойства. На верхнее окно и его фреймы необходимо ссылать- ссылаться с учетом их иерархических отношений. В ссылке на окно могут быть указаны свойства Window, такие как top, parent, window и self. Свойство top ссылается на главное окно (окно браузера), a parent — на мульти фреймовое окно, в котором содержится текущий фрейм.
Объекты Frame Для фреймов, содержащихся в верхнем окне, parent и top представляют собой одно и то же. Свойства self и window ссылаются на текущий фрейм или окно, Рассмотрим следующий код: <FRAMESET COLS=0%,*"> <FRftME SRC="doel.htnil" HAME="framel"> <FRAMESET COLS=0%,*"> <FRAME SRC="frame2.html" NSME="frame2"> <FRfiME SRC="doc3.html" NftME="frame3"> </FRAMESET> Файл frame2.html содержит следующую дополнитель- дополнительную информацию для установки фреймов в окне: <FRAMESET ROWS="*,20%"> <FRM1E SRC="doc4.html" NAME="frame4"> <FRRME SRC="doc5.html" NSME="frame5"> </FRAMESET> Родительским окном для frame 1, frame2 и frame3 является окно top, т.к. все эти фреймы содержатся в вер- верхнем окне. Родительским окном для framc4 и frame5 будет frame2, поскольку эти два фрейма находятся в окне frame2. Если необходимо сослаться на верхнее окно из документа, содержащегося в frame4, используют свой- свойство top; для ссылки на frame2 — свойство parent; и, на- наконец, для ссылки на собственный фрейм данного до- документа применяются свойства self или window. На функции, переменные и другие свойства можно ссылаться с помощью свойств Window: <HTMt> <Н?М» <TITLE>Frame Demo</TITIiE> <SCRIET LANGUAGE="JavaScript"> al = 2; function addAl () { a2 = al + 1; return a2 ; </SCRIPT> </HEAD> <BODY> <FRbMESET COLS=0%,*"> <FRAME SRC="docl.html" NAME="framel"> <FRAMESET COLS=0%,*"> <FRAME SRC="frame2.html" NAME="frame2"> <FRAME SRC="doc3.html" NAME="frame3">- </FRAMESET> ¦Файл frame2.html содержит следующую дополнитель- дополнительную информацию для установки фреймов в окне: <HTML> <HEAD> <TITLE>Frame Demo</TITLE> <SCRIPT LANGUAGE="JavaScript"> <! — Ы = 2; Глава 18 function addBl () { Ь2 = Ы + 1; return b2; )¦ // —> </SCRIPT> </HEAD> <BODY> <FRAMESET ROWS="*,20%"> <FRftME SRC="doc4.html" NftME="frame4"> <FRBME SRC="doc5.html" NAME="frame5"> </FRAMESET> Для ссьглок на переменную al и функцию addAl() из. framel, framc2 или frame3 используют top.al или parental, и, соответственно, top.addAl() либо parent.addAl(). Однако, для ссьглок из frame4 или frame5 можно исполь- использовать только top.al и top.addAl, т.к. parent ссылается на frame2. На переменную Ы и функцию addBl() из frame4 и frame5 можно ссылаться с помощью parent.bl и parent.addBl(). Хочется надеяться, что все это не выглядит слиш- слишком запутанно. Дополнительные способы ссьглок на раз- различные фреймы и окна будут обсуждаться в разделе "Ссылки на фреймы" далее в главе. При работе с фреймовыми документами и JavaScript необходимо соблюдать некоторые предосторожности. Сценарий может выполняться ошибочно, если фрейм содержит некорректный документ или даже вообще не содержитдокумента. Попытка сослаться на top.al из любого документа в предыдущем примере приведет к ошибке, если документ отсутствует во фрейме. Однако, JavaScript предлагает средства для предотвращения таких ошибок; такие сред- средства рассматриваются в следующем разделе. Синхронизация фреймов Как упоминалось ранее, при отсутствии правильных документов или корректно загруженных фреймов могут возникать ошибки и другие проблемы. Выполнение про- программы остановится на половине пути, если программа не сможет найти необходимую переменную. Кроме того, проблема может возникнуть по причине неполной заг- загрузки документа. Синхронизация фреймов гарантирует,, что загрузка фреймов и документов будет завершена прежде, чем в них возникнет необходимость, либо же будут предприниматься альтернативные действия. Проверка допустимости фреймов Часто проблема возникает, когда страница содержит JavaScript-код, который дает возможность просматри- просматривать документы в фреймах или без них. Свойство window.length обычно применяется для JavaScript- реше- решения о просмотре документов в виде фреймов. Свойство length хранит количество фреймов, содержащихся в окне.
Использование DOM Часть III Можно предусмотреть условный оператор, который ис- исполняет какое-либо действие, если будут использоваться фреймы: if( top.length != О ){ document.write ("Frames are being used") ; 1 Обычно вместо window используют top или parent, поскольку window подразумевает фрейм, содержащий внутри безфреймовый код (если документ не является файлом для установки других фреймов). Если окно или фрейм содержат фреймы, значение их свойства length будет больше нуля. Однако, если записать символ ">" (для "больше"), то в старых браузерах он может быть ¦ошибочно интерпретирован как завершающий символ HTML-комментария, поэтому предпочтительнее исполь- использовать символы "!=" ("не равно"). Применение короткого цикла с оператором if помо- поможет избежать ошибок, если документ, не находящийся во фрейме, попытается сослаться на переменную из дру- другого фрейма или мультифреймового окна. Если верхнее мультифреймовое окно содержит переменную al, кото- которая используется в операторе if в соответствие с создан- созданным документом, ошибка возникнет при просмотре дан- данного документа в автономном нефреймовом виде. Однако, если свойство length, заранее проверенное в условном выражении, равно false, то оператор if завер- завершает работу, предотвращая возникновение ошибки из- за попытки обращения к несуществующей переменной. Первая часть следующего оператора, parent.length != О, равна false, когда фреймы не используются, так что дальнейшее выполнение останавливается и ошибка не возникает: if( (parent.length != 0) && (top.al = X ) ) 'Проверка правильности загрузки документов Для синхронизации фреймов были разработаны различ- различные методы, некоторые из них довольно просты, в то время как другие — гораздо сложнее. Один из самых простых методов использует JavaScript для проверки наличия необходимого документа в данном фрейме пе- перед продолжением выполнения остальной части кода. Массив frames позволяет определять фрейм как элемент массива. (В разделе "Ссылки на окна и фреймы" далее в этой главе можно найти дополнительную информацию относительно массива frames.) Рассмотрим следующую строку кода: if( (parent.length == 3) &&(parent.frames [1] .title == "My Page") ) Оператор if проверяет правильность структуры фрейма (в данном случае — наличие трех фреймов), а также правильность документа во втором фрейме (на который в данном случае ссылаются). Если структура фрейма неправильна, вычисление условия останавлива- останавливается, и никаких дальнейших действий не предпринима- предпринимается либо же предпринимаются альтернативные дей- действия. Если структура фрейма корректна, но неправилен документ, сценарий не инициирует никаких действий либо реализует альтернативные действия. Если никакие дальнейшие действия не предпринимаются, программа просто остается в текущей позиции, разрешая пользо- пользователю продолжать выполнение других действий или повторить неудавшееся действие. (Возможно, страница не была до конца загружена, и следующая попытка заг- загрузки окажется успешной.) Альтернативные действия могут включать обеспечение сигнала для пользователя, загрузку правильной страницы и продолжение работы или же продолжение действия с пропуском шагов, тре- требующих обращений к отсутствующему документу. Предыдущий пример проверял простую фреймовую структуру (три фрейма). Можно проверять корректность и более сложных структур, используя массив frames раз- различных окон в составном операторе if. Составной опе- оператор if проверяет структуру сверху вниз, в противном случае ссылка на отсутствующий фрейм вызовет ошиб- ошибку. Рассмотрим следующую строку программы: if (top. length==3)&S(top.frames [1] .length=2NS (top.frames[l].frames[l]=3) . .. Если часть фреймовой структуры не существует, опе- оператор if останавливает работу в этой точке и сценарий выполняет альтернативное действие либо не выполняет никаких действий вообще. В ходе проверки наличия правильного документа код может проверять помимо заголовка и другие свойства, например, location.href фрейма. Вместо проверки заго- заголовка документа или другого свойства можно присваи- присваивать общей переменной в каждом документе уникальное имя или номер и затем проверять эту идентифицирую- идентифицирующую документ переменную. Регистрация документов Простая проверка присутствия требуемого документа в случае больших сайтов может стать слишком сложной, в этом случае проверку полной зафузки документа мож- можно не проводить. Другой выход из ситуации состоит в том, чтобы сами документы уведомляли, загружены ли они. Используя события onLoad() и <mUnload(), доку- документы регистрируют свое присутствие в переменной topWindow или в cookie-набора. Следующий код пока- показывает, что нет необходимости использовать заголовок для идентификации документа; можно использовать другое свойство или идентифицирующую переменную: <BODY onLoad="top. funRecord(document.title) " onUnload="top.funRemove(document.title)">
Объекты Frame Приведенный ниже пример демонстрирует простую схему регистрации документа. Первый фрагмент кода содержит файл для установки верхнего фреймового окна: <SCRIPT LANGUAGE="JavaScript"> <! — var a4 = ""; // переменная для регистрационной // строки документа function funRecord{ // добавить документ в // регистрационную строку при загрузке а4 += а; function JunRemove{ // удалить документ из // регистрационной строки при выгрузке а4 = а4.substring{ 0,a4.index0f ) + а4.substring<a4.indexOf+a.length,a4.length) ; function funCheck{ // проверка, зарегистрирован // ли документ if( a4.indexOf != -1) return true; else return false; I // —> </SCRIPT> ¦Следующий фрагмент кода показывает файл доку- документа: <HTML> <TITLE>The Harley FXSTC</TITLE> <SCRIPT IANGUAGE="JavaScript"> function ?unRegister{ // присутствует ли набор фреймов? (top.document.title == "Main Frameset") ) if( a ="R") top. funRecord(document, title) ; else top. funRemove(document.title) ; } function funCheck{ // зарегистрирован ли // документ? if( (top. length != 0 )&& (top. document. title = "Main Frameset") ) return top . ? unCheck ; else return false,- </SCRIPT> <BODY onLoad=" top. funRecord (document .title) " onCInload=" top. funRemove (document .title) "> Код, показанный ниже, проверяет, зарегистрирован ли документ: if( funCheck("The Softtail Series") ) top.frames[2].fxnames() ; // документ // аарегистрирован, продолжить выполнение else // документ не зарегистрирован, // выполнить альтернативные действия top.location.href = "http://www.foo.com/fx.html"; Глава 18 Использование расширенных схем регистрации Более сложные схемы регистрируют не только доку- документ, но также и позицию документа в иерархической структуре фреймов. Если позиция документа изменя- изменяется из-за различных возможных сценариев загрузки или модификации сайта, код, содержащий ссылки на документ, может находить документ с использованием информации о регистрации документа. Вместо приме- применения одной переменной или cookie-набора для полу- получения информации по регистрации, некоторые схемы используют массив переменных, в котором каждый эле- элемент (переменная) содержит идентификационную и позиционную информацию для зарегистрированного документа. Эти схемы сложны для установки, однако, их гораздо выгоднее использовать при проектировании очень больших сайтов, где маленькая ошибка в струк- структуре может вывести из строя коды ссылок во многих до- документах. Набор фреймов hldaho (http://hidaho.com/frameset/) — это схема регистрации, эффективная для больших, слож- сложных фреймовых структур. Она регистрирует функции и расположения функций во фреймовой структуре. Она определяет расположение фрейма, передавая его имя (self.name) родительскому фрейму, который присоединя- присоединяет к этому имени свое собственное имя и передает да- далее эту информацию родительскому фрейму. Процесс продолжается все выше по родительским окнам, вплоть до самого верхнего окна. Также имеется возможность снятия регистрации заданной функции (все функции должны иметь уникальное имя) и регистрации имени фрейма (всех функций, расположенных в этом фрейме) при закрытии документа. В набор фреймов hldaho включена функция для про- проверки, зарегистрирована ли указанная функция (она возвращает false, если указанная функция не зарегист- зарегистрирована), а также функция Ехес(), которая вызывает другие функции и передает им параметры. Поскольку все имена функции должны быть уникальны, разработ- разработчик получает возможность вызова требуемой функции, не зная ее расположения, и передачи параметров в нее через Exec (function, parameter!, parameter2,...). Обновления фреймов Существенная выгода, которую дают фреймы, заключа- заключается в возможности модификации документа во фрей- фрейме, не затрагивая при этом другой фрейм. Независимо оттого, обновляется ли фрейм с помощью ввода пользо- пользователя в другом фрейме или модифицируется программ- программно, существует несколько методов для внесения измене- изменений в соответствующие фреймы. Эти методы могут использовать HTML (с некоторыми расширениями Netscape), JavaScript или комбинацию их обоих.
Использование DOM Часть III Ссылки Возможно, самой простой методикой обновления сле- следует считать использование ссылок для изменения те- текущего фрейма (загружая новый документ). Для того чтобы направить новый документ в другой фрейм, ис- используют дескриптор якоря, имеющий атрибут target, для которого можно определить значение имени фрей- фрейма или относительное имя. Относительные слова (в Netscape они называются magic target names) соответству- соответствуют относительным свойствам окна, обсуждавшимся ра- ранее. Относительные имена, применяющиеся для целе- целевых ссылок, всегда начинаются с символа "_" и всегда записываются в нижнем регистре. Эти имена — _top, parent и _self — соответствуют свойствам окна top, parent и self. Однако, не существует имени _window. Следующий код представляет фреймы, в которых ссылка в одном фрейме должна обновить другой фрейм: COLS=0%,*"> <FRfiME SRC="docl.html" NMSE="framel"> <FRaMESET COLS=0%,*"> <FRAME SRC="frame2.html" NAME="frame2"> <FRMffi SRC="doc3.html" NAME="frame3"> </FRAMESET> Файл frame2.html содержит дополнительную инфор- информацию для установки фреймов в окне: <FRSMESET ROWS="*,20%"> <FRSME SRC="doc4.html" NAME="frame4"> <FRftME SRC=" doc5.html" NAME=" frame5 "> </FRAMESET> Для загрузки нового документа в frame2 с помощью ссылки в doc4.html (в frame4) эту ссылку записывают следующим образом: <А HREF="new.html" TARGET="_parent"> Для загрузки документа в верхнее окно и очистки всех фреймов используют такую строку: <А HREF="new.html" TARGET="_top"> Динамические ссылки Поскольку ссылки в JavaScript являются объектами, а href и target — свойствами ссылок, можно создать дина- динамическую ссылку, присваивая другие значения href и target: <А HREF="#" TARGET= "_top" onClick='this.href="new.html"; this.target="_self";'> Для поддерживающих JavaScript браузеров документ new.html загрузится в текущий фрейм; если же JavaScript не поддерживается, то текущий документ загружается в верхнее окно. (Спецификатор фрагмента, #, без URL и якорного имени, или идентификатор фрагмента, ссы- ссылается на текущий документ.) Переназначение свойств ссылки href и target можно сделать более динамическим путем объединения операторов присваивания с услов- условным и другими операторами. В следующем примере при использовании фреймов файл, устанавливающий фрей- фреймы, загружается в родительское окно; если же фреймы не используются, в окно загружается главный документ: <А HREF="main.html" TARGET="_top" ondick='if( top.length != О ) ** {this. href=" frameset! . html" ; ^this . target="_parent"; }" > Обратите внимание на кавычки; обработчик собы- событий должен быть заключен в кавычки (двойные или оди- одиночные). Нет необходимости переназначать свойства href и target для каждой динамической ссылки. В предыдущем примере атрибут target можно установить в _parent. Для нефреймовой версии _parent и top эквивален- эквивалентны. Если пользователь имеет неподдерживающий фрей- фреймы браузер, то атрибут target игнорируется. Пример мог быть написан этот путь: <А HREF="main.html" TARGET="_parent." onClick='if( parent.length != 0 ) ** {this .href="f ramesetl .html" ; } ' > Дескриптор ссылки может стать довольно длинным и громоздким, поскольку к его обработчику событий добавляется все большее количество операторов. Для упрощения ссылки можно использовать вызов функции: <А HREP="main. html" TARGET="_top" onClick=' this.href=theHref(); ¦¦•this. target=theTarget () ; ' > theHref() — пользовательская функция, которая вы- вычисляет условие и возвращает соответствующее значение для свойства href. Точно также theTarget() возвращает соответствующее значение для свойства target. Эти фун- функции должны вернуть значение независимо от того, яв- является ли вычисленное условие true или false; только неподдерживающий JavaScript браузер использует зна- значения по умолчанию, установленные с помощью атри- атрибутов TARGET и HREF. В качестве нефреймового аль- альтернативного примера рассмотрим следующий код: function theHref(){ if( top.length != 0 ) a = "framesetl.html"; else a = "main.html"; return a ; I Аналогично можно создать theTarget(). Таким же образом используют функции для других ссылок на стра-
Объекты Frame яйце, передавая соответствующие URL и целевые име- имена в вызовы функций. Возможно также для большого количества ссылок использовать одну-две универсаль- универсальных функции. Часто динамические связи не нужны. Как правило,, страница загружается в текущий фрейм, либо ссылка появляется в навигационном меню, которое не видимо в нефреймовой версии и всегда предназначается для определенного фрейма. Однако, в тех немногих случа- случаях, когда динамические ссылки необходимы, они ока- оказываются весьма эффективными. К тому же, поддержка фреймовой и нефреймовой версий — не единственный случай, где динамические ссылки бывают нужны; эти ссыл- ссылки можно устанавливать в любом случае, по желанию. Свойство location.href Другой способ обновления фрейма, который не обяза- обязательно требует применения ссылок, связан с использо- использованием свойства href объекта Location. Это свойство можно также применять вместе с обработчиком событий кнопки формы или с функцией. Не путайте объект Location со свойством location документа, document.location — свой- свойство только для чтения, однако можно записывать значе- значения в window.location.href. Следующие операторы экви- эквивалентны и модифицируют текущий фрейм, содержащий начальную страницу http://www.mcp.com/: location.href = "http://www.mcp.com/"; self.location.href = "http://www.mcp.com/"; window.location.href = "http://www.mcp.com/"; Следующие операторы обновляют, соответственно, родительское и верхнее окно: parent.location = "http://www.mcp.com/"; top.location = "http://www.mcp.com/"; Вместо использования относительных свойств Window можно использовать имя фрейма: parent.frame3.location.href = "http://www.mcp.com/"; В дополнение к записи свойства href можно также записывать свойство pathname объекта Location, которое позволяет определять путь или имя файла от корневого каталога сервера. (Конечно, имя хоста, равно как и про- протокол и порт, не зависят от текущей страницы сайта.) Для загрузки документа http://www.abc.com/foo/ doc2.html в framel, который в настоящее время имеет адрес: http://www.abc.com/index.htm, используется следу- следующий код: framel.location.pathnames"/foo/doc2.html"; Однако, если текущий документ находится по адре- адресу http://www.def.org/home.html или ftp://ftp.abc.com/ pub/abc.txt, необходимо задействовать свойство href. Глава 18 Метод write() Третий способ обновления фрейма состоит в примене- применении методов write() или writeln(). JavaScript может ди- динамически генерировать документ во фрейме: <HTML> <HEAD> <TITLE>Updating Demo Frameset</TITLE> </HEAD> <FRAMESET COLS=0%,*"> <FRftME SRC="docl.html" NftME="framel"> <FRAME SRC="doc2.html" NM4E="frame2"> </FRAMESET> </HTML> Файл docl . html Файлом docl.html может быть любой файл, даже пу- пустой. Однако, во избежание ошибки "Document contains no data" ("Документ не содержит данных") в файл необ- необходимо поместить, по крайней мере, пробел или символ возврата каретки. Динамически загружаемый фрейм может взаимодей- взаимодействовать с пользователем с помощью ссылок или форм: <HTML> <HEAD> <TITLE>Updating Demo framel</TITLE> <SCRIFT LMJGUAGE=" JavaScript "> <; — function docWrite () { top.frame2.document.clear(); top. Irame2 .document. write("<HTMLXHEAD>" + "<TITLE>Dpdating Demo f rame2</TITLE>" ) ; top . frame2 . document. write (" </HEADXBODY k-»BGCOLOR=\"" -I- document.forml.bginput.value + "\">"); top.frame2.document.write("<Hl>Updated Page top. frame2 .document.write ("Update by " + document.forml.inputl.value); top. frame2. document, write < "</ВОБУХ/НТМЦ»'; top. f rame2. document, closet) ¦ </SCRIPT> </HEM» <BODY> <FOKM NAME="forml" <INPUT TYPE="TEXT" NaME="inputl"> Select a Background Color<BR> <INPUT TYPE="RM)IO" NftME="radiol" VALUE="white" CHECKED onClick= ' document. f orml .bginput. value= "white"'>White<BR> <INPUT TYPE="RADIO" NAME="radiol" VALUE="red" onClick='document.forml.bginput.value= "red" '>Red<BR> <INPUT TYPE="RADIO" NAME="radiol" VALUE="blue" onClick= ' document. forml. bginput. value= "blue"'>Blue<BR> <INPUT TYPE="RAD10" NAME="radiol" VALUE="green" onClick=" document, forml. bginput. value=
Использование DOM Часть III '"green" ¦ >Green<BR> <P> <INPUT TYPE="HIDDEN" NftME="bginput" VALUE="white"> -CINPUT TYPE="BOTT0N" VALUE=" Update frame2" onClick="doeWrite()"> </FORM> </BODY> </HTML> JavaScript-код, используемый для обновления фрей- фреймов, может оказаться очень сложным. Можно применять условные операторы, вычисления или любой сценарий для создания документа, обновляющего фрейм. Игры, слайдовые демонстрации, карты изображений и резуль- результаты выполнения запросов в базы данных — вот только некоторые примеры использования обновлений фрей- фреймов. Кеширование файлов Загрузочные модули, которые требуется включить в об- обновляемый фрейм, могут заранее кешироваться для пре- предотвращения загрузки еще немодифицированного фрей- фрейма. Для кеширования изображения до момента, когда в нем возникнет необходимость, используют объект Image. Однако, этот объект недоступен в ранних верси- версиях JavaScript-браузеров. Другая методика загрузки изоб- изображения предполагает использование документа в скры- скрытом фрейме: <HTML> <HEAD> <TITLE>Hidden Frame to Cache Images</TITLE> </HEAD> <FRSMESET COLS=00%,*"> <FRAME SRC="docl.html" NAME="?ramel"> <FRAME SRC="cache.html" NftME="frame2"> </FRAMESET> </HTML> Следующий код — это неотображаемый документ, предназначенный только для загрузки изображений, что обеспечит запись изображений в кеш: <HTML> <HEAD> <riTLE>Updating Demo framel</TITLE> <SCRIPT LANGUAGE="JavaScript"> var al 0; </SCRIFT> </HEAD> <EODY onLoad="al = 1;"> <IMG SRC="imagel.gif" WIDTH=100 HEIGHT=200> <IMG SRC="image2. jgp" WIDTH=300 HEIGHT=120> <IMG SRC="iinage3.gif" WIDTH=2 00 HEIGHT=200> </BODY> </HTML> iB дескрипторах изображений необходимо указывать размеры для предотвращения проблем, возникающих при выполнении сценария в разных версиях браузеров. Несмотря на то что с дескрипторами изображений обычно советуют использовать атрибут alt, этот атри- атрибут в данном случае не обязателен, поскольку документ не должен отображаться в каком-либо браузере, в том числе и неграфическом. Переменная al — это флажок, который устанавли- устанавливается после полной загрузки изображения. Использо- Использовать этот флажок необязательно, но полезно для предот- предотвращения выполнения сценария модификации фрейма до полной загрузки изображений: if(top.frame2.al !=1 ) alert ("Please wait, ^downloading"); > elsef images are still , . .оставшаяся часть сценария Сценарии для фреймов с картами изображений В Netscape Navigator 2.0 была введена поддержка кли- клиентских карт изображений (хотя Netscape — не первый браузер, который стал это делать) наряду с фреймами и JavaScript. Клиентские карты изображений (Client-side imagemaps, CSIM) обеспечивают существенную выгоду по сравнению с существовавшими ранее серверными картами изображений. С помощью CSIM можно вклю- включать файл карты как отдельный файл в документ с изоб- изображением или ссылкой на него. Потребуется только отправить запрос на сервер для обработки и перенаправ- перенаправления на соответствующий URL. Пользователи будут видеть в строке состояния URL-адрес, связанный с кар- картой. Кроме того, CS1M можно использовать вместе со старыми серверными картами изображений с целью обеспечения совместимости со старыми браузерами. Свойства карт изображений С картами изображений связаны несколько объектов и свойств. Дескрипторы области изображения на карте яв- являются объектами JavaScript. Атрибуты href и target - свойства объекта Area, которые можно изменять про- программно через JavaScript. Объект Area содержит обработ- обработчики событий onClick, onMouseOver и onMouseOut. Фактически, объект Area имеет те же свойства и собы- события, что и объект Link. Дескриптор области имеет еще и атрибут nohref, который предотвращает загрузку URL документа, присвоенного атрибуту href.
Объекты Frame JS ПРИМЕЧАНИЕ ЙЧ Объекты и свойства карты изображений в ранних вер- версиях JavaScript-браузеров были не доступны. Объект Area и его свойства появились в JavaScript 1.1. Кро- Кроме того, в JavaScript 1.1 обработчик событий onClick и атрибут nohref не функциональны для всех платформ. Ссылки на объекты Area На объекты Area можно ссылаться с помощью массива links. Массив links содержит все объекты Link и Area в документе. Нумерация элементов начинается с нуля. Следующий код демонстрирует пример документа со ссылкой и CS1M. <HTML> <HEAD> <T1TLE>CSIM DEMtX/TITLE> </HEAD> <BODY> <A HREF="docl.html" target="?rameA">The Softtails <MAP NAME="mapl"> <A NAME="areaA" COORDS=0 ,20 , 80 , 80" HREF="doc2 .html" TARGET="f rameA"> <A NAME="areaB" COORDS=00,20,180,80" HREF="doc3 .html" TARGET="frameA"> <A NAME="areaC" COORDS=0 , 100 , 80 ,180" HREF="doc4 .html" TARGET="frameA"> <A NAME="areaD" COORDS=00 ,100,180, 180" HREF="doo5 .html" TARGET="frameA"> </MAP> <1MG SRC="mapl.gifn WIDTH=200 HEIGHT=200 ALT="Menu" USEMAP="#mapl"> < t ~- Код для альтернативных серверньк карт изображен!^ и текстовых меню для неграфических браузеров попросту опущен -->. </BODY> </HTML> В приведенном выше примере ссылка упоминается k;i к document.links[0], поскольку это первый дескриптор ссылки или области в документе. На область агеаАссы- агеаАссылаются как на document.lmksf 1], т.к. это второй дескрип- дескриптор ссылки или области, агеаВ — это document.links[2], агеаС — document.links[3] и, наконец, areaD — document. links[4]. На свойства href и target объектов Area, как и в слу- случае с объектами Link, можно ссылаться и присваивать им новые значения через массив links. Следующая строка кода изменяет значение свойства пгегдля агеаВ так, что- чтобы при нажатии на его область карты изображения вме- вместо doc3.html загрузился бы документ doc6.html: document. link [2 ]. href="doc6. html" Аналогично можно изменять свойство target: document.link [2].target="frameB" Свойство и атрибут target должны определяться как имя фрейма или одно из специальных относительных слов фрейма (_top, _parent, _self или _blank), но не как JavaScript-свойства (top, parent и т.п.). Глава 18 Можно открывать и устанавливать имена новым ок- окнам, присваивая target имя, которое уже не использу- используется. Новое окно, открытое таким способом, будет иметь имя, указанное в качестве значения атрибута target. Вызов функции Дескрипторы области не всегда должны ссылаться на документ. Можно осуществлять вызов функции, приме- применяя протокол javascript:, за которым следует имя функ- функции: <А NAME="areaA" COORDS=0,20,80,80" HREF="javascript:funl () "> Данный сценарий вызовет вместо документа опреде- определяемую пользователем функцию funl(). Можно также использовать методы и операторы JavaScript. Эта мето- методика особенно эффективна для фреймовой версии сай- сайта, в которой серверная карта изображений представле- представлена в виде навигационной кнопочной панели. Функция может включать различные операторы, предназначенные для определения использования фреймов и установки некоторых флажков либо проведения вычислений или оценок. Функция может тогда выполнять соответствую- соответствующее действие, например, загрузку некоторого докумен- документа, либо не выполнять никаких действий вообще. Следующие фрагменты кода содержат простой сце- сценарий слайдовой демонстрации с кнопочной панелью для карты изображений, которая позволяет циклически передвигаться вперед и назад в рамках последовательно- последовательности слайдов. Карта изображений также содержит кноп- кнопки возврата в меню, таким образом, пользователь может выбрать другую слайдовую демонстрацию или вернуть- вернуться на начальную страницу. Каждая слайдовая демонст- демонстрация имеет имя последовательности, которое свою пер- первую часть формирует из имен файлов слайдов. Вторая часть имени файла — порядковый номер, уникальный для каждого слайда в последовательности. Каждый из файлов слайдов имеет три переменных: имя последова- последовательности, порядковый номер слайда и общее количе- количество слайдов в последовательности. Сценарий читает эти три переменные, чтобы загрузить файл, опираясь на ту часть карты изображений, которая была нажата. Следующий фрагмент кода устанавливает фреймы: <HTML> <HEAD> <TITLE>Slide Show Main Frameset</TITLE> </HEAD> <FRAMESET ROWS="+,55"> <PRAME SRC="slidel.html" NAMK="frameA"> <FRAME SRC="button.html" NAME="f rameB"> </FRAMESET> </HTML> Ниже приведен код из файла slidel: <HTML>
Использование DOM Часть III <HEAD> <TITLE>Slide Show - First Slide</TITLE> <SCRIPT bANGUAGE="JavaScript"> var al = "slide";//первая часть имен файлов //слайдов var a2 = 1;// номер последовательности var аЗ = 3;// количество слайдов // --> </SCRIPT> </HEAD> <BODY> <IMG SRC="slidel.gif" WIDTH=300 HEIGHT=20Q ALT="The 1992 FXSTC, Softtail Custom"> </BODY> </HTML> Следующий фрагмент содержит файл кнопочной панели: <НТМ1> <НЕМ» <TITLE>Slide Show Demo Image Map</TITLE> <SCRIPT LANGUAGE="JavaScript"> function funl { al = top. frames [0] .al; // корневое имя файла // series последовательности слайдов а2 = top. frames [ 01 . а2; / / номер // последовательности аЗ = top.frames[0] . аЗ; // количество слайдов if{ a = "?" ) if(a2 = аЗ> а2 = 0; if ( а = "г" ) if(a2 = 1) а2 = аЗ - 1; else а2 я а2 - 2; а2 = а2 + 1; al += а2; al += ".html"; top.frames[0].location.href = al; } </SCRIPT> </HEAD> <BODY BGCOLOR=" 000000"> <MAP NBME="mapl"> <AREA COORDS=,1,75,50" HREF='javascript:funl("f") ' onMouseOver="window.status="Cycle forward wthrough slide show"; '¦return true'> <AREA COORDS=6,1,150,50" HREF="menu.html" TARGET= " f rameA" onMouseOver='window.status="Return to Menu wto Select Another Slide Show"; " re turn true'> <AREA COORDS=51,1,225,50" HREF="home.html" TARGET»"_top" onMouseOver='window.status="Quit Slide Show 4and Return to Home Page"; ^return true'> <AREA COORDS=26,1,300,50" HREF='javascript:funl("r")' onMouseOver='window.status="Cycle backward "• through slide show"; '"return true' > </MAP> <IMG SRC="buttons.gif" WIDTH=300 HEIGHT=50 USEMAP="#mapl "> </BODY> </HTML> Работа с фреймовыми URL Нет никаких принципиальных различий между URL фреймовых и нефреймовых документов. В случае фрей- фреймового окна, однако, можно заходить на различные сай- сайты и использовать различные базовые HREF. Один фрейм может содержать документ из одного каталога на сервере, другой фрейм — документ из другого катало- каталога, а третий фрейм может загружать документ вообще из другого сервера. Независимо от конкретного фрейма, к относительному URL в ссылке обращаются из доку- документа, содержащего ссылку. Можно использовать дес- дескриптор <BASE>, <BASE HREF="http://www.foo.com/ some.html">, в документе, чтобы установить все ссылки для базового HREF. Базовый HREF можно отменить, помещая в ссылку абсолютный URL. Как и в случае атрибута HREF дескриптора <BASE>, можно определить базовый целевой фрейм <BASE TARGET="frameA"> направляет все ссылки в докумен- документе на указанный фрейм. Можно также отменить базо- базовый целевой фрейм с помощью атрибута TARGET в ссыл- ссылке. Например, <HREF="some.html"TARGET="_self> отменяет целевой фрейм и загружает документ в соб- собственный фрейм. ^ПРИМЕЧАНИЕ" -'-'ft Дескриптор <BASE>, <BASE HREF="some.html" TARGET="someframe">, необходимо помещать в раз- раздел <HEAD> документа. Для дескриптора <BASE> не предусматривается какое-либо содержимое и не существует закрывающего дескриптора <BASE>. Этот дескриптор с атрибутами HREF и TARGET показан в ¦следующем примере: <HTML> <HEAD> <TITLE>Base Demo</TITLE> <BASE HREF="http://www.fqo.com/home.html" TARGET=" f rameA" > </HEAD> <BODY> Дополнительную информацию относительно исполь- использования URL в фреймах можно найти в этой главе, в основном, в следующем разделе и в разделе "Обновле- "Обновление фреймов". Ссылки на фреймы При работе с фреймовыми окнами в прикладных про- программах JavaScript, вероятно, потребуются другие спо- способы ссылок на окна. JavaScript обеспечивает четыре
Объекты Frame вида ссылок на окна. Каждый вид реализован как свой- свойство объекта Window. !¦ ПРИМЕЧАНИЕ" т. Отдельные окна браузера не имеют иерархической структуры; однако при ссылках на окно, содержащее код, который открывает другое окно, его зачастую на- называют родительским элементом. Новое открытое окно при этом называют дочерним. Любое новое окно может назначать переменную в других окнах, чтобы другие окна могли ссылаться на данное окно и его свойства. Для ссылки на свойство в новом окне про- просто используют windowName.property. Рассмотрим следующий код: newWindow = window.open(); newWindow.location.href = "http://www.incp.com/"," Хотя этот фрагмент и не обеспечивает наиболее эф- эффективный способ записи кода, он демонстрирует способ ссылки на свойство дочернего окна. Новое окно было открыто и получило имя (в данном случае, newWindow). Затем было присвоено значение location.href нового окна. Ссылки на текущее окно В главе 9 обсуждалось использование window для ссылок на текущее окно. Однако, тогда не было сказано, что объект Window также содержит свойство под названием window, которое может служить инструментом для ссыл- ссылки на само себя. Кроме того, свойство self объекта Window — это еще одно средство для ссылок на текущее или активное окно. Например, следующих две строки кода программы функционально эквивалентны: window, defaultstatus = "Welcome to the Goat Farm Home Page" self .defaults tatus = "Welcome to the Goat Farm Home Page" Поскольку как window, так и self — синонимы теку- текущего окна, может показаться странным, что оба они включены в язык JavaScript. Как было показано в пре- предыдущем примере, объяснение этому — гибкость; по же- желанию можно использовать как window, так и self. Однако, насколько полезными могут быть window и self, настолько же они могут привести к путанице, если подойти к этому логически. В конце концов, свойство объекта, которое используется как эквивалентный тер- термин для самого объекта, довольно необычно. Следова- Следовательно, будет удобнее считать window и self для объекта Window зарезервированными словами, а не свойствами. Поскольку window и self — свойства объекта Window, нельзя использовать и window, и self в одном и том же контексте. Например, следующий код работать не будет: window.self.document.write("<hl>Test.</hl>") Наконец, в мультифреймовых средах window и self всегда относятся к окну, в котором выполняется JavaScript- код. рРИМЙЧАНЙЕ В некоторых объектно-ориентированных или основан- основанных на объектах языках self может относиться к ак- активному объекту, независимо от его типа. В JavaScript self относится только к активным объектам Window или Frame — и ни к чему больше. Ссылки из родительского фрейма на дочерний Родительский фрейм может ссылаться на свой дочерний фрейм одним из двух способов. Во-первых, можно ис- использовать имя фрейма, которое определяется в парамет- параметре NAME дескриптора <FRAME>. Например, в следу- следующем коде переменная myFrameFlicka ссылается на имя фрейма frameA: <HEAD> <TITLE>Parent to Child Demo</TITLE> <SCRIPT LANGUAGE="JavaScript"> function childCall() { var myFrameFlicka = self.frameA.name </SCRIPT> </HEAD> <FRAMESET COLS=0%,*"> <FRAME SRC="docl.html" <FRAME SRC="doc2.html" </FRAMESET> </HTML> KAME="frameA"> NAME="frameB"> Во-вторых, можно ссылаться на дочерний фрейм, используя массив frames. Каждый фрейм в окне, или родительский фрейм, является элементом массива. На элементы массива frames ссылаются помощью frames [i], где i — число, соответствующее порядковому номеру фрейма в родительском окне. Фреймы пронумерованы от нуля до числа, на единицу меньшего общего коли- количества фреймов. Следующий код определяет четыре фрейма: <FRAMESET R0WS=5%,25%,25%,25%"> <FRAME SRC=" docl.html" NAME="f rameA"> <FRAME SRC="doe2.html" NAME="frameB"> <FRAME SRC="doo3.html" NAME="frameC"> <FRAME SFC="doc4.html" NAME="frameD"> </FRAMESET> Следовательно, массив frames данного окна будет содержать четыре элемента: frames [0 ] для фрейма frameA frames [1] ДЛЯ фрейма frameB frames [2] для фрейма frameC frames [3] ДЛЯ фрейма frameD Обратите внимание, что при ссылках на элемент массива frames в конце слова frames[i] присутствует "s", что указывает на множественное число.
Использование DOM О Часть Ссылки из дочернего фрейма на родительский Как было показано в данной главе, фреймы — это те же самые объекты Window, но внутри содержащего фреймы окна. Внутри мультифреймового окна возникает необ- необходимость различать между собой фреймы, отображае- отображаемые в браузере. Свойство parent объекта Window помо- помогает это делать, ссылаясь на родительское окно — окно, содержащее определение <FRAMESET>. Например, если требуется получить некоторую информацию о те- текущем родительском окне, используйте пример из лис- листинга 18.1. Листинг 18.1. childWindow.htm. <html> <head> <title>Child Window</title> </head> <SCRIPT LANGUAGE="JavaScript"> < ! — function getParentlnf о ( ) { myParentTitle = parent, document, title alert ("My daddy's name is " + myParentTitle) </SCRIPT> <form> < input type="button" value="Get Info" onClick="getParentInfо О"> </form> < /body> </html> Кроме получения значений свойств, можно также обращаться к методам родительского окна. Например, листинг 18.2 содержит исходный код HTML для роди- родительского окна фреймов с методом showlnfo(), опре- определенным без внутренней реализации. Листинг 18.3 показывает, как дочернее окно получает доступ к это- этому методу. Когда пользователь нажимает на объект childButton, его обработчик событий onClick вызывает runDadMethod() с передачей ключевого слова this в ка- качестве параметра. В свою очередь, runDadMethod() вы- вызывает метод showlnfo() объекта parent, передавая в па- параметре имя текущего объекта. На рис. 18.14 показан результат. Листинг 18.2. parentWindow.htm. <html> <head> <title>Parent Window Title</title> <SCRIPT IANGUAGE="JavaScript"> function showlnfo(objectName) alert(objectName) </SCRIPT> < /head> <Frameset Cols=5%,65%"> <Frame Name = "FRAME1" SRC="childWindow.htm"> <Frame Name = "FRAME2"> </Frameset> </html> СОВЕТ Для определения пустого фрейма следует престо опу- опустить атрибут SRC в конструкции <FRAME>. Листинг 18.3. anotherChildWindow.htm. _ <html> <head> <title>Child Window</title> </head> <SCRIPT IANGUAGE="JavaScript"> function runDadMethod(curObject) { parent, showlnfo(curObject .name) </SCRIPT> <form> <input type="button" name="childButton" value="Run Dad's Method" onClick="runDadMethod(this) </form> </body> </html> РИСУНОК 18.5. Вызовметода изродительского окна. Родительское окно зачастую представляет собой са- самое верхнее окно в мультифреймовой оконной среде, но это не обязательное требование. Существует также воз- возможность вкладывать разноуровневые коды установки фреймов друг в друга, как будет показано ниже, при
Объекты Frame обсуждении свойства top. Поэтому свойство parent ссы- ссылается на непосредственное родительское окно текущего окна. При необходимости обратиться к родительскому окну следующего уровня используют строку вида: myGranddadTitle = parent.parent.document.title В более сложных фреймовых структурах на любой из фреймов можно ссылаться, используя их позицию в иерархии фреймов, как показано на рис. 18.6 и в табл. 18.2. top window frameA frame В frame С frame D frame E frameEA frameEB frameBA frameBB I frameBBA frameBBB РИСУНОК 18.6. Иерархическая структура сайта с вложенными фреймами. Таблица 18.2. Ссылки на другие фреймы из frameBBB. Фрейм Ссылка frameA frameBA frameBB frameEA top.frameA или top.frames[0] top.frames[1].frameBA или top.frames[1].frames[0] parent, top.frames[1].frameBB или top.fratnes[1 ].frames[1 ] top.frames[4].frameEA или top.frames[4].frames[0] Приведенная ниже строка используется для ссылки на заголовок документа в frameEA и присвоения его переменной al: al — top.frames[4].frames[0].document.title; На другие свойства ссылаются совершенно аналогич- аналогично. ПРИМЕЧАНИЕ Важнс обратить внимание на различия в иерархии, которые могут существовать между двумя похожи- похожими на вид фреймовыми структурами, как было пока- показано в разделе "Создание фреймов" ранее в главе. В JavaScript версии 1.1 и выше появилось свойство opener, которое обычно ссылается на окно (родительс- (родительское), из которого было открыто текущее окно. Из ново- нового (дочернего) окна можно ссылаться на свойство от- открывшего его родительского окна через top.opener, property. Для ссылки на родительское окно из нового откры- открытого окна в JavaScript 1.0 можно прибегнуть к методике Глава 18 присваивания. Обычно здесь используют свойство top объекта Window; однако, в случае необходимости вмес- вместо top можно использовать self, parent или window. В следующем фрагменте кода используется свойство top, поскольку код должен появляться в любом из фреймо- фреймовых окон. Использование top гарантирует, что соответ- соответствующее свойство окна верхнего уровня будет иденти- идентифицировано, self, parent или window может означать любой фрейм в окне верхнего уровня. newWindow = window, open("docl.html") ; newWindow. oldWindow = top; Используйте приведенный ниже синтаксис для ссыл- ссылки на свойство в открывшем окне из открытого нового окна: top.oldWindow.proper ty Использование ссылок из дочернего окна на дочернее окно Свойство parent важно не только для доступа к родитель- родительскому окну из дочернего, но также и для ссылки на любой другой объект в одном из дочерних окон того же уровня. Как показано на рис. 18.7, любая связь между дочерними фреймами должна быть реализована через их родительское окно. На фреймы одного уровня с разными родительски- родительскими окнами необходимо ссылаться, используя их абсо- абсолютную позицию в иерархической структуре: <FRAMESET COLS=0%,*"> <FRAME SRC="docl.html" KAME="frameA"> <FRAME SRC="doc2.html" HAME="frameB"> </FRAMESET> В этом примере OKHoframel ссылается на значение кнопки '»: в окне frame2. Данное окно может сделать это с помощью свойства parent: buttonLabel = parent.frame2.documentform[0].okButton.value РИСУНОК 18.7. Использование свойства parent для ссылок па элементы того же уровня.
Использование DOM Часть III Следующий фрагмент содержится в docl.html: -«FRAMESET ROWS=0%,*"> <FRSME SRC="doc3.html" NaME="frameAA"> <FRAME SRC="doo4.html" ЫЙМЕ=" frameAB "> </FRAMESET> Следующий фрагмент содержится в doc2.html: <FRAMESET ROWS=0%,*"> <FRAME SRC=" doe5.html" NSME="frameBA"> <FRAME SRC="doc6,html" NAME="?rameBB"> </FRAMESET> framt'BB ссьглается на frameAB таким способом: top.frames[0].frameAB Можно также использовать следующую строку: -top. frames [О] .frames [0 ] Для межуровневых ссылок не существует промежу- промежуточного уровня между верхним и родительским окном, такого как "прародительское окно". Это, видимо, к луч- лучшему, что родительское окно — единственный термин, позаимствованный из генеалогии; представьте на секун- секунду, что ссылка на фрейм выглядела бы как third, cousin, twice, removed (игра слов: что-то типа "дважды убрать третьего двоюродного брата"). Если окнам браузера в момент открытия всегда при- присваиваются имена, для одного из новых (дочерних) окон не будет проблемой сослаться на другое дочернее окно через открывшее его (родительское) окно. В этом слу- случае потребуется просто упомянуть имя окна, как было показано в предыдущих разделах. Если окну в момент открытия присвоено имя переменной myWindow, другое дочернее окно может ссылаться на него таким способом: top.opener.myWindow Можно синхронизировать окна теми же методами, которые применяются для фреймов. Однако, при отсут- отсутствии единственного окна верхнего уровня браузера или иерархии окон, одно окно, открывшее другие окна, вы- выбирается в качестве точки синхронизации. Следующий фрагмент кода — это пример сценария синхронизации окон: <HTML> <TITLE>The Harley FXSTC</TITLE> OCRIPT LANGUAGE="JavaScript"> <!-- ¦ function ?unRegister{ // проверить, что страница находится в своем // окне, а открывающееся окно содержит / / корректный документ if( (top.name=="newWindowl"> &? (top. opener .document.title="Main Frameset") ) if( a ="R") top.opener.funRecord(document.title) ; else top . opener. funRemove (document. title) ; function funCheck{ // зарегистрирован ли // документ if ( <top.name=="newWindowl") && (top.opener.document.title=="Main Frameset") re turn top .opener. f unCheck ; else return false; </SCRIPT> <BODY onLoad="top. funRecord (document.title) " onUnload="top. funRemove (document.title) "> Следующая программа проверяет, зарегистрирован ли документ: if( funCheck("The Softtail Series") newWindow2 . frames [2] . fxnames () ; // документ II зарегистрирован, продолжить действия else // документ не зарегистрирован, // инициировать альтернативное действие top. location.href = "http://www.foo.com/fx.html"; Как и в случае фреймов, можно использовать более сложные схемы для регистрации информации о распо- расположении документа. В этих схемах применяются те же самые сценарии, как и для фреймов, но с добавлением еще одного уровня для включения отдельных ОКОН бра- браузера. Окно верхнего уровня Подобно свойству parent в функции, свойство top объек- объекта Window позволяет ссылаться на самое верхнее окно в пределах мультифреймового окна или в наборе мульти- фреймовых окон. При работе с одним мультифреймовым окном свойства parent и top ссылаются на одно и то же окно. Однако, если имеются вложенные уровни мульти- фреймовых окон, top обращается только к окну самого высокого уровня, a parent может ссылаться как на это, так и на другое родительское окно. * СОВЕТ , В окне верхнего уровня и родительских окнах удоб- удобнее всего хранить глобальные методы. Различие между данными окнами лучше всего про- проиллюстрировать на примере. Предположим, что имеет- имеется два набора фреймов. Первый набор фреймов делит окно браузера горизонтально на фреймы, занимающие 80% и 20% пространства (как показано на рис. 18.8). Второй набор фреймов разделяет на четыре квадранта (показанные HajjHC. 18.9) нижнее, занимающее 20%, подокно окна самого верхнего уровня. Предположим, что для каждого дочернего фрейма требуется получить заголовки его верхнего и родитель- родительского окон. Для этого можно определить общую функ- функцию с именем getNameQ, которая бы возвращала эту информацию вызвавшему ее окну. Так же, как дочер- дочерние окна могут обращаться к методам родительского
Объекты Frame окна, все фреймы в мультифреймовом окне имеют дос- доступ к методам окна верхнего уровня. Таким образом,, окно верхнего уровня — это удобное хранилище для функций, которая должна быть глобально доступна для всех окон. Метод getName() определяется следующим образом: function getName (callingObject, relation, parentName) { callingObject.document.write ("My " + relation + "'s name is " + parentName +".") . htm frmain.htm bottomFrameset.htm I Глава 18 Этот метод getName() вызывается дочерним фрей- фреймом после загрузки. Его можно вызывать, помещая сле- следующий код в каждом дочернем фрейме: <SCRIPT LANGUAGE="JavaScript"> top. getName (self, "parent" , paren t.document.ti tie) document.write("<p>") top.getName (self, "top", top.document. title) </SCRIPT> Сценарий использует top для обращения к методу getName(), использует self для идентификации себя в качестве вызывающего окна, а также parent и top для получения заголовков окон. На рис. 18.10 показан ре- результат после загрузки фреймов. Листинги 18.4, 18.5 и 18.6 содержат исходный код для мультифреймового окна верхнего уровня (topFrameset.htm), мультифреймового окна нижнего уровня (bottomFrameset.htm) и одного из дочерних фреймов нижнего уровня (bottomSubFramel.htm). Листинг 18.4. topFramesethtm. _ <HTML> <HEAD> <TITLE>Top-Level Frameset</TITLE> <SCRIPT LANGUAGE="JavaScript"> function getName(callingObject, relation, parentName) ( callingObject. document, write ("My " + relation + ' ' s name is " + parentName + РИСУНОК 18.8. Мультифреймовоеокно верхнего уровня. bottomFrameset.htm bottomSubframe2.htm РИСУНОК 18.9.Мультифреймовое окно нижнего уровня. Параметр callingObject представляет окно, вызываю- вызывающее функцию. Используя точечную нотацию, в преде- пределах рассматриваемого окна можно выполнять команду document.write. Параметры relation и parentName стро- строки, обеспеченные вызывающим окном, но не управля- управляемые в данной функции. </SCRIPT> </HEAD> <FRAMESET ROWS="80%,20%"> <FRAME SRC=" frmain.htm" NAME="main" MARGINWIDTH=" 1 " MARGINHEIGHT=" 1 " > <FRAME SRC="bottomFrameset.htm" NAME=" footnotes" MARGINWIDTH=" 1 " MARGINHEIGHT=" 1 " > <NOFRAMES> Warning text should go here for browsers with no frame support. <BODY> </BODY> </NOFRAMES> </FRftMESET> </html> Листинг 18.5. bottomFrameset.htm. <HTML> <HEAD> <TITLE>Lower-Level Frameset</TITLE> </HEAD> <FRAMESET COLS=4%,24%,24%,28%"> <FRRME SRC= "bottomSubframel. htm" > <FRAME SRC="bottomSubframe2.htm"> <FRAME SRC="bottomSubframe3.htm">
Использование DOM Часть III <FRAME SRC="bottomSubframe4.htm"> </FRAMESET> </HTML> My partnt't nimt Is Top-Ltv»l Frameset. My tops лвтч Is Top-Levei Frameset. toy-top's name l> Тор-Level Frameset Mytop'snamels Тор-Level Frames* Mytop's name is Top-Lev*"! Frameset i РИСУНОК 1&10. Свойства parent и top. Листинг 18.6. bottomSubFrame1.htm. <HTML> <HEAD> tnotes Frame in Bottom Frameset</TITIiE> <SCRIPT IANGUAGE="JavaScript"> top.getName(self, "parent", ^•parent .document. title) document.write("<p>") top.getName(self, "top", top.document.title) </SCRIPT> </HEAD> <BODY> </BODY> </HTML> ПРИМЕЧАНИЕ V Возможная проблема, связанная со ссылками на до- документы в других фреймах и окнах — ограничения си- системы безопасности, которая не дает JavaScript дос- доступа к свойствам документов другого сервера. Начиная с Netscape Navigator 2.02, это ограничение было ре- реализовано с целью защиты информации о списке по- посещений пользователя, о паролях в HTML-формах, структуре каталогов и других конфиденциальных эле- элементах. Netscape Navigator 3.0 обеспечивает меру безопасно- безопасности, называемую data tainting (разрушение данных), которая разрешает пользователям обращаться к до- документам другого сервера без возможной угрозы для системы безопасности. С технологией разрушения данных код JavaScript может ссылаться и пользовать- пользоваться свойствами документов из других серверов. Полу- Полученные данные разрушаются (или портятся) так, что- чтобы их невозможно было переслать на другой сервер без пользовательского подтверждения (с целью обес- обеспечения безопасности и секретности). Более подробная информация о методике разрушения данных находится в главе 35. . ¦ Объект Location Объект Location формирует URL текущей страницы. Он имеет двойное назначение: Устанавливает объект Location для перехода на но- новый URL. Извлекает определенные элементы URL и работает с ними. Без объекта Location для получения необхо- необходимой информации потребовалось бы выполнять оп- определенные манипуляции над строкой URI... Основная структура URL такова: protocol/Vhostname: port pathname search hash Типичный URL может выглядеть, например, так: http://www.acadians.com/javascript/search/ "•Hats?qt=RFC+1738fScol=XL Свойства объекта Location, каждое из которых явля- является элементом URL, сведены в табл. 18. Таблица 18.3. Свойства объекта Location. Атрибут Описание HREF Полный URL. PROTOCOL Начальный элемент URL (информация до двоеточия). HOSTNAME Хост и имя домена либо IP-адрес. HOST Элемент Hostname:port (Имя хоста:порт) из URL PORT Коммуникационный порт сервера. PATHNAME Элемент пути URL. SEARCH Часть определения запроса URL (ь с символа "'» HASH Якорное имя URL (начинается с символа "#"). ПРИМЕЧАНИЕ Важно отличать объект Location от свойства location объекта Document. Значения объекта Location изменять можно, а свойство location объекта Document предназ- предназначено только для чтения. Открытие нового URL Вместо использования специального метода перехода к новому URLb окне, можно просто открыть новый URL, установив значение объекта Location. Интересно заме- заметить, что это можно сделать, присваивая значение URL объекту непосредственно или же присваивая данное значение свойству href объекта Location. Например, сле- следующих две строки выполняют одно и то же действие:
Объект/ Frame window.location = "http://www.acadians.com/" window.location.href = "http://www.acadians.com/" Для создания с помощью JavaScript окна редактиро- редактирования URL, можно использовать код, приведенный в листинге 18.7. Листинг 18.7. moveTo.htm. <HTML> <HEAD> <SCRIPT LANGUAGE "JavaScript"> function moveon() { var urlAddress = urlAddress = document.forms[0].Editl.value window.location = urlAddress 3 </SCRIPT> </HEAD> <BODY> <FORM> <INPOT type="text" name="Editl"> <INPUT type="button" value="move" onClick="moveon()"> </FORM> </BODY> </HTML> В мультифреймовых окнах можно определить значе- значение объекта Location в других фреймах, ссылаясь на со- соответствующее имя окна. Например, рис. 18.11 демон- демонстрирует мультифреймовое окно, в котором можно изменять URL с помощью ввода текста в форму, распо- расположенную в нижнем фрейме. Листинг 18.8 показывает исходный код для этого нижнего фрейма. [This page intentionally left blank.] 3rotocol//hostname:port pathname Г РИСУНОК 18.11. Использование объекта Location для изменения URL другого фрейма. Листинг 18.8. frfootno.htm <html> <head> <title>Footnotes Frame in Location Object Example</title> <SCRI]?T LANGUAGE="JavaScript"> Глава 18 function gotoPageO { parent.frames[O].location.href = window.document.loc.ProtocolField. options [window.document, loc. "¦• ProtocolField.selectedlndex] . text document.loc.HostnameField.value + document.loc.PathnameField.value i </SCRIPT> </head> <body> <pXfont size=5>protocol//hostname:port pathname </fontX/p> <form name="loc" method="POST"> Hostname: Pathname: <select name-"ProtocolField" size=l> <option>http://</option> <option>file://</option> <option>javascript:</option> <option>ftp:</option> <option>mailto:</option> <option>gopher:</option> <option>about:</option> </select> <input type=text size=23' maxlength=256 name="HostnameField" value="www.typehere.com"> <input type=text size=20 maxlength=100 name="PathnameField" value="/"> <input type=button name="Go" value="Go" onClick="gotoPage() "X/pre> </form> </body> </html> Работа со свойством protocol Свойство protocol объекта Location позволяет определять тип текущего URL. Таблица 18.4 содержит часто ис- пользуемыепротоколы. Таблица 18.4. Протоколы объекта Location. Тип URL Протокол Web File FTP MailTo Usenet. Gopher JavaScript Navigator http: file: ftp: imailto: news: gopher: javascript about:
Использование ЮМ Часть III Объект History Все, кто много времени провел в Web, вероятно, знако- знакомы со списком посещений браузера. Также, как список посещений позволяет пользователю возвращаться на посещенные сайты, так же объект History в JavaScript позволяет JavaScript-разработчику переходить к ранее посещенным Web-страницам. Объект History не имеет никаких событий, а только свойства и методы, перечис- перечисленные в табл. 18.5 и 18.6. Таблица 18.5. Свойства объекта History. Свойство Описание current URL текущего документа. length Длина списка посещений. next Следующий URL в списке посещений. previous Предыдущий URL в списке посещений. Таблица 18.6. Методы объекта History. Метод Описание Васк() Загружает предыдущий документ из списка посещений. Forward() Загружает следующий документ из списка посещений. Go() Переходит кзаданномудокументу. Go(n) Если л> 0, загружает документ, который находится на л пунктов дальше в списке посещений. Go(string) Загружает документ из списка посещений, URL которого содержит указанную строку. Определение размеров списка Для определения количества посещений в списке мож- можно использовать свойство length объекта History. Пред- Предположим, что требуется отследить число посещений пра- правого фрейма мультифреймового окна. Левый фрейм содержит следующий код: <HTML> <HEAD> <SCRIPT LANGUAGE = "JavaScript"> function moveon() { var urlAddress = "" urlAddress = document. forms [ 0] . Editl. value parent.frames[1] .location = urlAddress document.forms[0].Edit2.value = parent.frames[1].history.length </SCRIPT> </HEAD> <B0DY> <FOKM> type="textn name="Editl"> <INPUT type="button" value="move" onClick="moveon()"> <IMPUT type="text" name="Edit2"> </FORM> </B0DY> </HTML> Пользователь может применять текстовый объект Editl для ввода целевого URL. Когда пользователь щел- щелкает на кнопке "Move" для перехода на указанный URL, текстовый объект Edit2 изменяется и отображает длину списка посещений правого фрейма. Навигация по списку посещений Одно знание длины списка посещений редко оказыва- оказывается особо полезным, однако оно может принести боль- больше пользы, если требуется перемещаться по списку с использованием объекта History. Перемещение на одну страницу назад Метод back() функционально эквивалентен щелчку на кнопке "Back" (стрелка влево) в инструментальной па- панели браузера. Например, следующий код перемещает окно в его предыдущую позицию: window.history.back() Перемещение на одну страницу вперед Как и следовало ожидать, метод forward() — то же, что и щелчок на кнопке со стрелкой вправо в инструмен- инструментальной панели браузера. Этот метод используется ана- аналогично: window.history.forward{) Переход к указанной странице по номеру в списке Метод go() используется для перехода к определенно- определенному месту в списке посещений. Его синтаксис таков: [window. ] history .go <delta | "location") Параметр delta — положительное или отрицательное целое число, которое определяет количество шагов пе- перехода. Например, следующая строка — это переход к следующему документу в списке посещений (эквива- (эквивалент использования метода forward()): window.history.goA) Таблица 18.7 содержит возможные значения delta. Таблица 18.7. Значения delta. Метод' Описание delta < 0 Перемещает назад на delta пунктов. delta > 0 Перемещает вперед на delta пунктов. delta = 0 Перегружает текущий документ.
Объекпи Frame Переход куказанной странице по строке в списке В качестве альтернативы можно использовать параметр location для определения заданного URL в списке. Об- Обратите внимание, что здесь не нужен точный URL, a только подстрока. Следующий пример позволяет пере- перемещаться к URL в списке посещений, который содер- жит\?\те.аса<Цап8.сот/Шепе\?: window.history.go("www.acadians.com/filenew") В приведенный выше пример можно добавить back(), forward() и go() для обеспечения более полной функци- функциональности мультифреймовой системы навигации. На рис. 18.12 показано мультифреймовоеокно. Листинг 18.9 содержит исходный код HTML для родительской стра- страницы мультифреймового окна, а листинг 18.10 — код для списка посещений. Правая область окна не содержит никакого JavaScript-кода. Ways to and КзлнвпХ) methods. Ш r By court с By Name JavaScript Chronicles — Free Subscription Form 1, What other magazines do you currently subawbe to? Г К Веек Г №15 Г Imrnbascil 4dvi3DE Г Internet Icivlsor Г PC flwatiue Г BelphL MaiMnt Г Deb In РИСУНОК 18.12. Пример фрейма History, Листинг 18.9. HistoryFrames.htm._ <html> <head> <title>History Object Example</title> </head> <Frameset Cols=5%,65%"> <Frame Name = "FRAMEl" SRC="History.htm"> <Prame Name = "FRRME2" SRC="JavaScriptChronicles.htm"> </Frameset> </html> Листинг 18.10. History.htm. <html> <head> <title>History Page</title> </head> <body bgcolor="#FFFFFF"> <SCRIPT IANGaAGE="JavaScript"> <i — function goPrev<) { Глава 18 parent. frames [ 1 ] . history. back () functiongoNext ( ) { parent. frames [ 1] . history . forward () functionmoveOn ( ) { var urlAddress = ' urlAddress = document. forms [ 0 ] . LocationBox. value if (urlAddress != "") { parent, f rames [1).location= urlAddress document, forms [0] - ListLen. value = parent, frames [1] .history .length) else { alert ("Please enter a URL before ^clicking the Go button.") function jump() ( if (document.formsfO].goParamfl] .checked) ( var goVal = 0 goVal = parselnt (document, forms [0J .GoBox. value) ) else { var goVal = "" goVal = document.forms[0].GoBox.value ,1 parent, frames [1] .history.go(goVal) </SCRIPT> <form method="POST"> <h3Xem>Ways to navigate</em></h3> <li>Use the location object. </li> <pxinput type=text size=20 maxlength=50 name="LocationBox"> <input type="button" value="Find" onClick="moveOn() ' <li>Use the history object's <em>back(></em> and<em> forward() </em>methods. <input <p align=centerXinput type="button" value="Slt;ilt," onClick="goPrev() type="button" value=" figt; Sgt;" onClick="goNext() "x/p> <ul> <li>Use the history object's <em>back<) </em> and<em> forward() </em>methods. <blockquote> <p><input type=radio name="goParam" value="ByCount">By Covmt</p>
Использование DOM Часть III <pxinput type=radio name="goParain" value="ByNanie">By Name</p> <pxinput type=text size=20 maxlength=30 name="GoBox"> <input type="button" value="Go" onClick="jump() "> </p> <p>History List Entries: <input type=text size=3 maxlength=4 name="ListLen"> </blockquote> </form> </body> </html> Объект Navigator Объект Navigator — единственный объект, который выг- выглядит невписывающимся в иерархию встроенных объек- Таблица 18.8. Свойства объекта Navigator. тов JavaScript. На первый взгляд, казалось бы, этот объект является верхним уровнем пирамиды, посколь- поскольку программное обеспечение браузера (элемент, пред- представленный объектом Navigator) содержит информацию относительно браузера, выполняющего сценарий. Одна- Однако, объект Navigator не имеет никакого отношения к другим объектам в иерархии; в действительности, он обособленный объект, обеспечивающий только способ получения информации о текущем браузере. «ПРИМЕЧАНИЕ *"¦'¦ Sf- "¦": Имейте в виду, что объект Navigator невозможно ис- использовать для получения информации от браузеров, которые не поддерживают JavaScript. Если браузер не поддерживает JavaScript, он не будет обрабатывать запрос на информацию. Очевидно, что невозможно применить JavaScript-подпрограмму для определения, поддерживает ли браузер JavaScript. Объект Navigator имеет свойства, показанные в табл. 18.8. Свойство Описание appName appVersiorii appCodeName userAgent. appCodeName AppMinorVersion AppName AppVersion BrowserLanguage ConnectionSpeed CookieEnabled CpuClass OnLine Language MimeTypes Platform Plugins SystemLanguage UserAgent UserLanguage UserProfile Имя браузера. Версия браузера. Кодовое имя браузера. Заголовок user-agent для браузера. Кодовое имя браузера; поддерживается в Navigator 2 и Internet Explorer 3. Подверсия версии браузера; поддерживается в Internet Explorer 4. Имя браузера; поддерживается в Navigator 2 и Explorer 3. Версия браузера; поддерживается в Navigator 2 и Explorer 3. Языковая конфигурация браузера; поддерживается в Explorer 4. Скорость, на которой браузер выполнил соединение; поддерживается в Explorer 4. Работает ли браузер с cookie-наборами; поддерживается в Explorer 4. Класс процессора на платформе браузера; поддерживается в Explorer 4. Указывает, находится ли браузер в режиме он-лайн; поддерживается в Explorer 4. Языковая конфигурация браузера; поддерживается в Explorer 4. MIME-типы, поддерживаемые браузером; согласуется с Navigator 3 и Explorer 4. Операционная система, под управлением которой работает браузер; поддерживается в Navigator 4 и Explorer 4. .Массив подключаемых модулей, установленных в настоящий момент; поддерживается в Navigator 3 и Explorer 4. Язык операционной системы по умолчанию; поддерживается в Explorer 4. Заголовок user-agent, посылаемый с браузера на сервер; поддерживается в Explorer 3 и Navigator 2. Пользовательский язык; поддерживается в Explorer 4. Доступ к информации пользовательских профилей; поддерживается в Explorer 4.
Объекты Frame Объект Navigator поддерживают как Netscape Navigator, так и Microsoft Internet Explorer. Листинг 18.11 демон- демонстрирует пример отображения информации о браузере в диалоговом окне, когда пользователь нажимает на кнопку "Show Browser Info". Рисунки 18.13 и 18.14 по- показывают сигнальные окна сообщений, которые появ- появляются в результате работы сценария, соответственно, в Netscape и в Internet Explorer. Листинг 18.11. navigatorlnfo.htm. <HTML> <HEAD> <SCRIPT LANGUAGE = " JavaScript"> function displayBrowserlnfо() ( var browserStr = ' browserStr += "Browser: ' + navigator.аррЫате + "\r" browserStr += "Version:" + navigator.appVersion + "\r" browserStr += " ' + navigator.appCodeName + "\r" browserStr += "User agent: " + navigator. userAgent + "\r" alert(browserStr) ¦</SCRIPT> <BODY> <H1X/H1> <FORM> < INPUT Type="button" Value="Show Browser Information" OnClick="displayBrowserInfo()" </lNPOT> </FORM> </BODY> </HTML> .. . РИСУНОК 18.14. Информация о браузере в Microsoft Internet Explorer. Резюме В этой главе детально рассматривались мультифреймовые и одиночные окна. Объекты Frame, Location и History обеспечивают средства для работы с соответствующи- соответствующими аналогами браузеров. Объект Navigator, намного отличающийся от других объектов JavaScript, позволя- позволяет извлекать информацию о текущем браузере. В главе также обсуждались методы использования JavaScript для ссылок на объекты и свойства в других фреймах и окнах браузера. Были приведены базовые примеры создания окна и установки фреймов, а также рассмотрены способы ссылок на свойства в различных фреймах и окнах. Кроме того, были даны способы об- обновления и синхронизации фреймов и окон, а также несколько примеров окон и фреймов, взаимодействую- взаимодействующих друг с другом через JavaScript. Использование JavaScript на фреймовом сайте не- несколько более сложно, чем использование его на не- нефреймовом сайте, однако полученные выгоды зачастую стоят небольших дополнительных усилий по преодоле- преодолению трудностей. Кратко рассматривались несколько примеров сочетания JavaScript с фреймами и окнами. Возможные применения и реализации фреймового сайта ограничиваются только воображением разработчика Web-сайта и степенью его трудолюбия. РИСУНОК 18.13. Информация о браузере в Netscape Navigator.
Другие DOM-объеюы В ЭТОЙ ГЛАВЕ DOM-браузеры Управление DOM-документами и DOM-методы В главе 13 были рассмотрены основные принципы объектной модели документа (DOM) и показана стан- стандартизация DOM-модели с помощью интуитивно по- понятных представлений в виде деревьев. В этой главе с задействованием ряда листингов на JavaScript, рас- рассматривается практическое применение общих DOM- методов. Кроме того обсуждаются различные DOM- узлы и элементы и практические способы управления ими, а также некоторые важные проблемы, связанные с браузерами. DOM-браузеры DOM-модель использует части документа для представ- представления логической иерархии с помощью дескрипторов страниц, их последовательности, свойств и атрибутов. Последние изменения DOM в Netscape Navigator и Internet Explorer связаны с работой консорциума W3C. С помощью Netscape Navigator 3 могли быть написаны и прочитаны атрибуты изображения и якорные деск- дескрипторы, можно было запрашивать информацию о том, какие подключаемые модули имеются в наличии, какие MIME-типы поддерживаются и т.п. В Navigator 4.0 были Таблица 19.1. XML- и HTML-узлы документов. предоставлены дескрипторы для уровней дерева и усо- усовершенствованы методы определения ширины и высо- высоты контейнеров и окон. Исторически этот уровень DOM-модели был поддержан в JavaScript, и как Java- аплеты, так и подключаемые модули могли управлять DOM с помощью LiveConnect, который является основ- основным кодом языка создания сценариев JavaScript. В Internet Explorer 4.0 DOM-модель интегрирована непос- непосредственно в браузер, а не через язык создания сцена- сценариев. Это помогает устранить несоответствия между раз- разными языками создания сценариев, например, различия в позициях дескрипторов. В результате информация ста- становится стандартизованной и непротиворечивой для различных браузеров, причем для взаимодействия с DOM теперь возможно использовать JavaScript, VBScript, элементы управления ActiveX, Java-аплеты и любые другие компоненты языка, совместимые с DOM API, записанным в OMG IDL. Из этого следует, что исследования навигационных процессов в главе 13 было уместным. Узлы ранее описывались как составные час- части DOM-деревьев и, как упоминалось в главе 13, имен- именно узлы дают возможность программам взаимодейство- взаимодействовать с содержимым документа. Все узлы перечислены в табл. 19.1. Узел' Описание Атрибут Раздел CDATA Комментарий Тип документа Свойство дескриптора: например, элемент img может иметь атрибут src. Текстовое содержимое, за исключением символов метки. Метод createCDATASection создает узел со значением, которое является заданной строкой. Комментарии для страницы, описывающие код и другие аспекты Web-страницы или всего Web-сайта. Каждый документ содержит объект DocumentType или атрибут doctype, который может быть и null. Интерфейс DocumentType обладает возможностью перечислять такие специфические объекты.
Другие DOM-объекты Глава 19 Узел' Описание Document Объектное представление полного документа. Интерфейс Document представляет полный HTML- или XML-документ и предоставляет стандартные методы создания объектов Document, которые включают элементы, текстовые узлы, комментарии и команды обработки. Получившиеся объекты Node имеют атрибут ownerDocument. Element За исключением текста, большинство узлов Element — наиболее общие объекты, по которым авторы перемещаются при навигации по документу, как показано в следующем XML-примере: <element(Jnleashed id=[sq1]Unleashed demo[sq2]> <subelement1/> <subelement2><subsubelement/></subelement2> </elementUnleashed> Очевидно, что DOM-дерево содержит в качестве самого верхнего узла узел Document, содержащий узел Element для elementUnleashed, который, в свою очередь, содержит два дочерних узла Element, subelementi и subelement2, при этом subelementi дочерних узлов не имеет. Ссылка на сущности (объекты) Префикс амперсанд (&) указывает, что объект вставлен в документ с помощью ссылки. Используя DOM Level 2 версии 1.0, редактировать узлы Entity невозможно; скорее, .каждый EntityReference в структурной модели потребуется заменять копией содержимого' реального объекта, только после этого появится возможность их модификации. Дочерние элементы узла Entity предназначены только для чтения, при этом узлы Entity родительских элементов не имеют. Атрибуты systemld типа DOMString (только для чтения). Содержит заданный идентификатор системы либо null, если он не определен. notationName типа DOMString (только для чтения). Содержит имя примечания для непроанализированных объектов либо null для проанализированных. publicld типа DOMString (только для чтения). Содержит заданный общий идентификатор либо null, если он не определен. Ссылка на элемент, атрибут или строку текста. Команда для синтаксического XML-анализатора; D0M сохраняет эту информацию обработки в XML-документах. Атрибуты Адрес типа DOMString (только для чтения). Это адрес команды обработки или первого маркера после команды обработки. Данные типа DOMString — содержимое команды обработки, которая находится между первым символом (кроме пробела) после адреса и символа непосредственно перед "?>". Text Объект, содержащий текст. Узел Команда обработки ПРИМЕЧАНИЕ DOM-модель WWW-консорциума (W3C) поддержива- поддерживается в Netscape Navigator бив Microsoft Internet Explorer 5. В Navigator 4 написан новый HTML для объекта Layer. Для изменения текстового элемента с заданным ID и значением newtext форма приобретет следующий вид: var lyr = document.layers[id].document lyr.openO lyr.write(newtext) lyr . close () Internet Explorer 4.0 реализует другой способ и пре- предоставляет HTML-элементы документа, использующие ключевое слово ALL. Для изменения текстового эле- элемента с заданным ID и значением newtext форма по- получает следующий вид: document, all [id] -innerHTML = newtext Explorer 5 использует ключевое слово ALL для дости- достижения совместимости сверху вниз. A Navigator 5.0 для обеспечения совместимости сверху вниз сохраняет мо- модель Layers для объектов. "СОВЕТ . ' _¦ - - , ¦ ' i r' :-j В DHTML версии 4 для всех браузеров потребуется создать разветвление кода, с помощью которого вы- выясняется тип браузера и выполняются соответствую- соответствующие корректировки: ns4 = (document.layers)? true:false ie4 = (document, all) ? true .-false function simpleLayerWrite(id,newtext) {
Использование DOM Часть III if <ns4) ( var lyr = document.layers[id].document lyr. open () lyr.write(text) lyr.close() else if (ie4) document, all [id] . innerHTML = newtext Далее будет рассматриваться, главным образом, DOM IIES-реализации (и механизм браузера Gecko). Это при- примечание, однако, может очень скоро потерять акту- актуальность, возможно, уже сейчас Netscape Navigator и Explorer имеют совместимую DOM-модель. Управление DOM-документами и DOM-методы Теперь известно, что DOM-модель содержит полезные и практические методы управления объектом или струк- структурой узла документа. Это дает общие методы для вы- выполнения простых вещей, таких как копирование, вставка и замена узлов. Подобного рода методы позво- позволяют формировать легко заменяемые документы, ко- которые любой разработчик сможет изменить и понять при условии, что он знаком с DOM-моделью. Методы предоставляют образцы для непосредственного создания документов, а также используют ключевой аспект осно- основанных на объектах документов — возможность повтор- повторного использования, следовательно, вместо многократ- Листинг 19.1. Метод cloneNode. НОГО создания новых узлов и объектов их можно про- просто копировать. Таким образом, теперь мы вплотную подошли к "гайкам и болтам" этих методов и их прак- практического применения при создании и управлении до- документами, которые рассматриваются в следующих раз- разделах. Использование метода cloneNode Выполнение метода cloneNode задается с помощью его логического параметра in. Когда он равен true, копиру- копируется полное поддерево данного узла. С другой стороны, значение false данного параметра заставляет браузер копировать только указанный узел и игнорировать его дочерние и родительские элементы. Применение мето- метода cloneNode продемонстрировано в листинге I9.1, где параметр false используется для копирования только узла, без поддерева. Сценарий не делает ничего, кроме создания массива узлов, включенных в таблицу, и эте» достигается с помощью HTML. Сценарий на JavaScript содержит метод cloneNode, с помощью которого опре- определяется узел, предназначенный для копирования, а также вызывается сигнальный диалог, отображающий состояние копируемого узла. В этом примере сигналь- сигнальное сообщение показывает, что метод cloneNode вернул копируемый объект. К данной информации добавляет- добавляется отображение того, что копируемый объект не имеет никаких дочерних и родительских элементов, т.е. копи- копировался только узел. Замена в методе значения парамет- параметра cloneNode с false на true заставляет браузер копиро- копировать полное поддерево, включая дочерние и родительс- родительские элементы узла. <HTML> <HEAD> <TITLE> DOM cloneNode example </title> </HEAD> <BODY ID="bodyNode"> <TABLE ID="tableNode"> <TBODY> <TR ID="trlNode"XTD BGCOLOR="yellow">Row 1, Cell K/TDXTD BGC0LOR="orange">Row 1, Cell 2</TDX/TR> <TR ID="tr2Node"XTD BGCOLOR="red">Row 2, Cell K/TDXTD BGCOLOR="magenta">Row 2, Cell 2</TDX/TR> <TR ID="tr3Hode"XTD BGCOLOR="lightgreen">Row 3, Cell K/TDXTD BGCOLOR="beige">Row 3, Cell 2</TDX/TR> <TR ID="tr4Node"XTD BGCOLOR="blue">Row 4, Cell K/TDXTD BGCOLOR="lightblue">Row 4, Cell 2</TDX/TR> <TR ID="tr5Node"XTD BGCOLOR="orange">Row 5, Cell K/TDXTD BGC0LOR="purple">Row 5, Cell 2</TDX/TR> </TBODY> </TABLE> <SCRIPT IANGUAGE="JavaScript"> tr3Obj = trlNode.cloneNode(false) ; alert{ "tr3Obj.firstChild = " + tr3Obj .firstChild + "\n" + "tr3Obj .nodeName = " + tr30b j. nodeName
Другие DOM-объекты II —> </SCRIPT> </BODY> </HTML> Глава 19 Использование метода insertBefore в DOM Метод insertBefore обеспечивает средства формирова- формирования объектных структур, помещая заданные объекты перед другими указанными объектами. Здесь использу- используются два параметра, которые являются объектами: tbodyObj.insertBefore(tr20bj, tr30bj) Возможное использование метода insertBefore (рав- (равно как и других DOM-методов) — это формирование таблицы. Например, можно создать узел, скопировать его и затем использовать insertBefore для создания таб- таблицы. Листинг 19.2 показывает конструкцию таблицы, построенной с использованием этих методов. Объект tbodyObj содержит три дочерних объекта: trlObj, tr2Obj и tr3Obj, которые создаются с помощью следующих вы- выражений: trlObj = document.createElement ("TR"); trltdlObj = document. createElement ("TD"> ; trltd2Obj = trltdlObj.cloneNode (false); tr2tdlObj = trltdlObj.cloneNode <?alse); При использовании метода insertBefore объекты со- собираются следующим образом: tbodyObj.insertBefore < tr30bj); tbodyObj.insertBefore (tr2Obj, tr3Obj); tbodyObj.insertBefore (trlObj, tr2Obj); trlObj.insertBefore (trltd2Obj); trlObj. insertBefore (trltdlCbj, trltd2Obj); tr20bj.insertBefore (tr2td2Obj); tr2Obj. insertBefore (tr2tdlCbj, tr2td2Obj); Как видно из приведенного выше кодового фрагмен- фрагмента, последний дочерний объект (tr3Obj) вставляется в первую очередь, второй дочерний объект вставляется перед ним, а первый дочерний (trlObj) вставляется пе- перед вторым (tr2Obj). Листинг 19.2. Создание таблицы с помощью insertBefore. <H?ADJ>- <T1TLE> Building tables using DOM </TITLE> </HEAD> <BODY ID= "bodyNode "> <SCRIPT IANGUAGE="JavaScript"> rowlcolumnlObj = document.createTextNode("Row 1, *¦* column 1 ") ; tableObj = document. createElement ("TABLE") ; tbodyObj = document.createElement("TBODY") ; trlObj = document. createElement ("TR") ; trltdlObj = document.createElement("TD"); trltd2Obj = trltdlObj.cloneNode(false); tr2tdlobj = trltdlObj.cloneNode(false) ; tr2td2Obj = trltdlObj.CloneNode(false); tr3tdlObj = trltdlObj.cloneNode(false); tr3td20bj = trltdlObj.cloneNode(false); tr2Obj tr3Obj = trlObj.cloneNode(false); ¦ trlObj.cloneNode(false); rowlcolumn20bj row2columnlObj row2column20bj row3columnl0bj row3column20bj rowlcolumn20b j. nodeValue = row2columnlObj.nodeValue = rowlcolumnlObj.cloneNode(false); rowlcolumnlObj .cloneNode (false) ; rowlcolumnlObj.cloneNode(false); rowlcolumnlObj.cloneNode(false); rowlcolumnlObj.cloneNode(false); "Raw 1, column 2; "; "Row 2, column column column column row2column20bj .nodeValue = "Row 2, row3columnl0bj ,nodeValue = "Row 3, row3column20bj ,nodeValue = "Row 3, return Value = tableObj . insertBefore (tbodyObj) ; tbodyObj.insertBefore(tr3Obj); tbodyObj.insertBefore(tr2Obj, tr3Obj); tbodyObj.insertBefore(trlObj, tr2Obj); trlObj.insertBefore(trltd2Obj); trlObj.insertBefore(trltdlObj, trltd2Obj); tr2Obj.insertBefore(tr2td2Obj); tr2Obj.insertBefore(tr2tdlObj, tr2td2Obj); tr3Obj.insertBefore(tr3td2Obj); tr3Obj.insertBefore(tr3tdlObj, tr3td2Obj); trltd2Obj.insertBefore(rowlcolumn20bj); trltdlObj.insertBefore(rowlcolumnlObj); tr2td2Obj.insertBefore(row2column20bj); tr2tdlObj . insertBefore (row2columnl0bj) ; tr3td2Obj . insertBefore(row3column20bj); tr3tdlObj.insertBefore(row3columnlObj); bodyNode.insertBefore(tableObj); // --> </SCRIPT> </BODY> </HTML> Использование метода swapNode Метод swapNode меняет местами указанные поддеревья, встроенные в указанные узлы. Этот метод возвращает целое поддерево. Применение метода swapNode демон- демонстрируется в листинге 19.3. Функция printChildObjects печатает дочерние элемен- элементы bodyNode вместе со свойством nodeName. Использование метода removeNode Выражение removeNode(false) удаляет указанные узлы и присваивает их дочерние объекты родительскому объек- объекту удаленного узла: erasedNode = p3Node.removeNode(false); Листинг 19.4 иллюстрирует использование метода removeNode, а также применения функции printChildObjects.
Использование DOM Часть III Листинг 19.3. Перемещение абзацев. <SCRIPT LANGUAGE="JavaScript"> var msg = "" ; function printChildObjects() { childcount = bodyNode.childNodes.length; msg += "bodyNode. childNodes . length = " + bodyNode . childNodes . length + "\n" ; for (var i = 0; i < childcount; i++) { msg += "bodyNode.childNodes[i].nodeName = " + bodyNode.childNodes[i].nodeName + "\n" 1 ) printChildObjects(); msg += "Swap Paragraph 2 with paragraphl\n" ; var b = p2Node; var swappingNode = p3Node.swapNode(b); msg += " swappingNode. nodeName = " + swappingNode. nodeName + "\n"; msg += "swappingNode.childNodes.length = " + swappingNode.childNodes.length + "\n"; msg += "p2Node. nodeName = " + p2Node. nodeName + " \n"; printChildObjects () ,- alert(msg); // — > </SCRIPT> Листинг 19.4. Удаление узлов._ <SCRIPT IANGUAGE="JavaScript"> var msg — " ; function printChildObjects() { childcount = bodyNode. childNodes. length; msg += "bodyNode.childNodes.length = " + bodyNode.childNodes.length + "\n" ; for (var i = 0; i < childcount; i++) { msg += "bodyNode.childNodes [i] .nodeName = " + bodyNode. childNodes [i] .nodeName + "\n" printChildObjects 0; msg += "Erase paragraph 3\n" ; var deletedNode = p3Node. removeMode (false) ; msg += "deletedNode. nodeName = " + deletedNode. nodeName + "\n"; msg += "deletedNode.childNodes.length = " + deletedNode.childNodes.length + "\n" printChildObjects (); alert(msg); </SCRIPT> "СОВЕТ. ,: ' v ' >¦ DOM-объекты обращаются к полному содержимому Web-страницы, включая и графику, которая может храниться в формате GIF. Первый графический сим- символ в документе можно изменить путем замены его свойства src (src означает "source" — источник). В показанной ниже DOM-форме первое изображение просто заменяется на изображение с именем NewTitle в формате GIF. window.document.images[0].src='New_Title.gif ' ; Изображения в формате GIF и другие графические файлы можно редактировать в пакете Paint Shop Pro от Jasc Software. Эта программа распространяется свободно и ее можно выгрузить со множества сай- сайтов, в том числе и с сайта Jasc. Она имеет полезные инструментальные средства редактирования и эффек- эффекты, необходимые для создания превосходной Web- графики. Резюме ¦Эта глава, посвященная D0M, представляет собой еще один шаг вперед в изучении JavaScript. В ней обсужда- обсуждались способы создания и изменения составляющих сущностей документа. Таким образом, зная структуру и характеристики DOM-модели, ее можно применять буквально где угодно, используя практически любой программный объект, включая приведенные выше сце- сценарии. Вне этих сценариев можно проделывать то же самое с элементами управления ActiveX и Java-аплета- ми. Можно смело заявить о том, что появился новый ландшафт стандартизованных целевых платформ или клиентских браузеров, которые впервые общаются на том же языке, который определяет DOM-модель.
Технологии программирования на динамическом HTML ЧАСТЬ 20. Динамическая подмена 21. Визуальные эффекты 22. Каскадные таблицы стилей 23. Слои 24. Меню и панели инструментов DHTML 25. Взаимодействие с другими технологиями
Динамическая подмена В ЭТОЙ ГЛАВЕ Знание событий Виды динамических подмен Динамическая подмена (rollover) — это общий ме- метод совершенствования страниц сайта с использовани- использованием JavaScript. Фактически, это — одна из первых гло- глобально используемых функций JavaScript, сохранившая свою популярность до сих пор. Другие методы, такие как прокручиваемые сообщения строки состояния и тек- текстовые поля, исчезли с горизонта. Знание событий Создавая rollover-эффекты в рамках сайта, необходимо глубоко разбираться в соответствующих событиях JavaScript, Несмотря на то что события уже рассматри- рассматривались в главе 14, стоит все же вернуться кданной теме. onMouseOver Событие onMouseOver используется объектами Link и Document для определения момента установки указателя мыши на элементе. Internet Explorer позволяет захваты- захватывать эти события практически всем элементам на стра- странице, а не только объекты Links и Document. Пример демонстрирует захват событий onMouseOver дескрип- дескриптором <а>: <а href="http://www.mcp.com" onmouseover="alert('You rolled over!')"> Here</a> onMouseOut Событие onMouseOut весьма напоминает onMouseOver и точно так же может быть использовано объектами Link и Document. Это событие определяет, когда указатель мыши покинул конкретный элемент. Internet Explorer позволяет захватывать это событие практически всем элементам на странице, а не только объектам Link и Document: i href ="http: //www.mcp.com" onmouseout="alert ( ' You rolled off ! ) ">Here</a> onMouseDown Событие onMouseOut используется объектами Link и Document с целью определения момента нажатия кноп- кнопки мыши на определенном элементе. Для примера рас- рассмотрим захват событий onMouseDown в дескрипторе ">Here</a> <а href="http://www.mcp.com" onmousedown="alert('You pressed! onMouseUp Событие onMouseUp используется объектами Link и Document для определения момента отпускания кноп- кнопки мыши, ранее нажатой на определенном элементе. В примере показан захват таких событий в дескрипторе <а href="http : //www.mcp. com" onmouseup="alert ( 'Youreleased! ' ) ">Here</a> Виды динамических подмен Каждому разработчику необходимо не только решать, какой вид rollover-эффектов необходим на сайте, но и как его реализовать. Многие rollover-эффекты могут имитировать другие, поэтому все зависит только от пользовательского браузера и от того, что именно под- поддерживает этот браузер.
Динамическая подмена Глава 20 Rollover-эффекты для изображений Существует несколько методов реализации rollover-эф- rollover-эффектов для изображений (rollover-изображений), но са- самый простой заключается в создании двух массивов, содержащих используемые изображения и ссылки в документе на индексные расположения в массиве document.image. Необходимо сохранить все изображе- изображения в массиве объектов Image. Расположим на страни- странице два объекта специально для примера, представлен- представленного на рис. 20.1. Когда пользователь помещает курсор поверх изображения, происходит замена изображения на его rollover-версию. Массив изображений создается с использованием следующего кода: // Создание массивов для хранения изображений var overling = new Array () ; overling[0] = new Image B4 ,24) ; overlmg[l] = new Image B4 ,24) ; var defaultlmg = new Array(); defaultImg[0] = new ImageB4,24); defaultlmg[l] = new ImageB4,24); II Предварительная загрузка изображений в // массивы overlmg[0].src = "back-over.gif"; overling[1] .sre = "forward-over.gif"; defau.'.tlmg [0 J .src defaultlmg[l].src "back, gif"; "forward.gif" РИСУНОК 20.1. Страница с rollover-эффектами Следующий необходимый элемент — это функция, выполняющая собственную подмену изображений. Эта функция принимает два аргумента: первый — индекс- индексное расположение подменяемого изображения, а второй — вид свопинга ("over" или "out"). Оператор switch опре- определяет, из какого массива берется заменяющее изобра- жениг. После определения массива присваивание, обес- обеспечивающее замену изображения, реализуется через свойство src объекта Image: function rolllmage(img,type){ switch(type){ case "over": document.images[img].src = overling [img] .src; break; case "out": document.images[img].src = defaultlmg[img].src; break; Последний шаг связан с захватом событий onMouseover и onMouseOut. Как упоминалось ранее, это достигается с использованием дескриптора <а>. В' листинге 20.1 показан полный исходный код для зах- захвата событий, а на рис. 20.2 — замененное изображение, когда над ним находится указатель мыши. Листинг 20.1. Полный исходный код для реализации rollover-изображений <html> <head> <title> JavaScript Unleashed-»:/ title> <script type="text/javascript" language="JavaScriptl.2"> // Создание массивов для хранения // изображений var overling = new Array () ; overlmg[0] = new Image B4,24) ,- overling [1] = new Image B4 ,24) ; var def aultlmg == new Array () ; defaultImg[O] == new Image B4,24) ; = new ImageB4,24); // Предварительная загрузка изображений в // массивы overlmg[0].src = "back-over.gif"; overlmg[l].src = "forward-over.gif"; defaultImg[0].src = defaultlmg[l].src = "back.gif"; "forward.gif" // Изменение состояния изображения // зависимости от события function rolllmage<img,type){ switch(type){ case "over": document, images [img].src = overling [img] .src; break; case "out" : document, images [img] .src = defaultlmg[img].src; break; II—> </script> </head> <body bgcolor="#ffffff"> <table border="l" cellpadding=" cellspacing="O" align="center"
Технологии программирования на динамическом HTML Часть IV Ьдсо1ог="#сОсОсО"> <tr> <td align="center"> <а href="javascript:void@) " onmouseout="rolllmage<'0','out')" orunouseover="rolllmage< '0', 'over')"> <img border=" src="baok.gif" width=4" height=4" alt="Back"> </td> <td align="center"> <a href="javascript:void@)" onmouseout="rolllmage ( ' 1', ' out1) " onmouseover="rolllmage( ' I1 , 'over')"> <img border=" 0 " src="forward.gif"width=4" height=4" alt="Forward"X/a> </td> </tr> </table> </body> </html> РИСУНОК 20.2. Динамическая замена одного I изображений ПРИМЕЧАНИЕ В главе 24 прш гея более конкретные примеры rollover-изображений и подробно рассматривается их использование. Rollover-эффекты для слоев Следующий рассматриваемый нами вопрос — это реа- реализация rollover-эффектов для слоев. Они генерируют- генерируются за счет сокрытия и отображения слоев внутри доку- документа. Эта тема также затрагивается и в главе 23. Сейчас стоит кратко рассмотреть вопрос реализации доступа к свойству visibility таблиц стилей (CSS) в JavaScript. Первое, что потребуется сделать — создать HTML- документ, который станет основой примера. Здесь не- необходимо определить ссылку и изначально скрытый слой. Результирующий документ предельно прост. <div name="layerl" id="layerl"> Hello World! <a href="javascript: void<0)" onmouseout="changeState('layerl','hidden')" onmouseover="changeState{'layerl', Rollover to show and hide the layer. He беспокойтесь, что сейчас слоям уделяется мало внимания, поскольку эта тема рассматривается позже, в главе 23. В настоящий момент лучше сфокусировать внимание на коде JavaScript. Так же, как и в примере с rollover-изображениями, для захвата событий onMouseOver и onMouseOut будет использоваться дескриптор <а>. В дескрипторе <а> можно заметить три фрагмента кода. Первый фрагмент находится в атрибуте href. Этот вызов (javascript: со- сообщает браузеру о том, что при условии выполнения щелчка кнопкой мыши на ссылке ничего больше не про- произойдет (void(O)). Второй и третий фрагменты шзыва- ют функцию changeState() и передают ей две перемен- переменные. Первая, name (для браузеров Navigator) и id (для браузеров Internet Explorer) — это экземпляр слоя, а вторая — индикатор, который скрывает или отобража- отображает слой. СОВЕТ В атрибуте href допускается применение такого син- синтаксиса, на который ссылаются как на "JavaScript URL", для вызова функции либо для любого другого кода на JavaScript. ¦ ¦ . .... .. Следующий шаг заключается в установке таблицы стилей для слоя, которая обеспечит его сокрытие. Не- Несмотря на то что в CSS присутствует несколько свойств, которые будут рассматриваться в главах 22 и 23, сейчас примем во внимание только одно свойство visibility. Несложно заметить, что ему присваивается значение hidden. #layerl{ background-color: red; height: 100; left: 10; position: absolute; top: 50; width: 100; visibility: hidden; </style> Следующая часть кода необходима лишь для того, чтобы учесть отличия реализации слоев в браузерах Navigator и Internet Explorer. Вначале потребуется оп-
Динамическая подмена ределить, какой из браузеров получает доступ к страни- странице, и установить переменные, которые позволят исполь- использовать одну функцию для обработки rollover-эффектов. Детали реализации обсуждаются в главе 23. Сейчас рас- рассмотрим только код: ,// Создание глобальных переменных для хранения // типа браузера. var isIE = new Boolean (false) ; var isNav = new Boolean (false) ; var layer = new String () ; var style = new String () ; // Определение, является ли браузер Internet // Explorer, Navigator и др. Кроме того, // установка переменной слоя в зависимости от // необходимого способа доступа. function checkBrowser () ( if(navigator.userAgent.indexOf("MSIE") != -1) { is IE = true; layer = ".all"; style = " . style" ; }else if (navigator, user Agent. indexOf ("Nav") ! = -1>( isNav = true; layer = ".layers"; style = "" ; Последняя функция в данном примере отображает и скрывает слой. Так же, как и в HTML-документе, она принимает два параметра: имя слоя и состояние, на ко- которое требуется переключить слой. Благодаря проделан- проделанной ранее работе, функция содержит только одну стро- строку кода: function changeState(layerRef, state){ eval("document" + layer + "['" + layerRef + "¦]" + style + ".visibility = ¦» + state + ) ; .1 В функции используется верхнеуровневый метод eval(), который принимает объект String и выполняет его как код JavaScript. В нашем примере строка "document" + layer + »[ •» + layerRef + »¦ ] •• + style + ".visibility = ¦" + state + ""'); получает значение document.layerst'layerl'].visibility = "hidden"; для случая браузера Navigator и document, all [ ' layerl' ] . style .visibility = "bidden"; для случая Internet Explorer. Сейчас несложно заметить различия между видами доступа к слоям в этих двух браузерах. Теперь, когда создание кода завершено, можно оце- оценить результаты его работы. В листинге 20.2 предостав- предоставлен полный исходный код, а на рис. 20.3 — страница в Глава 20 браузере. Рисунок 20.4 демонстрирует rollover-эффекты для слоя. Листинг 20.2. Пример реализации rollover-эффектов для слоев <html> <head> <title> JavaScript Unleashed</title> <style type="text/css"> <!--¦ #layerl{ background-color: red; height: 100; left: Im- Imposition: absolute; top: 50 ; width: 100; visibility: hidden; </style> <script type="text/javascript" language="JavaScriptl.2"> // Создание глобальных переменных для // определения типа браузера. var isIE = new Boolean (false) ; var isNav = new Boolean(false); var unsupported = new Boolean (false) ; var layer = new String () ; var style = new String () ; // Определение, является ли браузер // Internet Explorer, Navigator или // каким-либо другим. Установка значения // переменной слоя в зависимости от вида // доступа. function checkBrowser() { if(navigator.userAgent.indexOf("MSIE") != -D{ isIE = true; layer = ".all"; style = ".style"; } else if(navigator.userAgent.indexOf("Nav") ¦- -1){ isNav = true; layer = ".layers"; style = ""; )else{ unsupported = true; ,// Take the state passed in, and change it.. function changeState (layerRef, state) { eval( "document" + layer + "['» + layerRef + "']" + style + ".visibility = "' + state + "'"); } II—> </script> </head> <body onload="checkBrowser()"> <div name="layerl" id="layerl"> Hello World Г
Технологии программирования на динамическом HTML Часть IV <а href="javascript :void@) " onmouseout="changestate('layer 1 ' , 'hidden') " onmouseover="changeState<'layerl','visible')"> Rollover to show and hide the layer. </body> </html> РИСУНОК 20.3. Ссылка без воздействия rollover-эффекта ПРИМЕЧАНИЕ И в Internet Explorer, и в Navigator предусмотрены собственные реализации CSS, поэтому не удивляйтесь, если результаты запуска некоторых сценариев будут отличаться. Например, при загрузке кода из листинга 20.2 Navigator 4 окрашивает только фон текста, а не весь слой. РИСУНОК 20.4. Rollover-эффект в действии Резюме Несмотря на небольшой объем главы, были описаны важные характеристики приложений JavaScript. Реали- Реализация rollover-эффектов на собственном сайте — одно из простейших и безопасных задач в JavaS t Но не стоит ограничиваться только информацией, полученной из книги. Rollover-эффекты могут лежать в основе мно- многих задач, решаемых с использованием JavaScript. Они позволяют глубже понять события и доступ к элемен- элементам страницы, а также знакомят с дизайном интерфей- интерфейсов. Остальная часть книги посвящена вопросам созда- создания визуальных эффектов, CSS и слоев. Будут рассмат- рассматриваться особенности создания на DHTML инструмен- инструментальных панелей и меню. Также будут исследоваться способы взаимодействия компонентов на стра] с ис- использованием JavaScript.
Визуальные эффекты В ЭТОЙ ГЛАВЕ Бегущие строки Баннеры Постепенное изменение цветов Анимированные командные кнопки На сегодняшний день такие технологии, как JavaScript и Java, широко применяются в сфере разработки Web- приложений. Они популярны также благодаря изящ- изящным операциям, которые можно проделывать с их по- помощью на Web-сайте. Вспомните, сколько бесполезных Java-аплетов блуждали по Web во времена, когда возрос- возросла популярность Java. Однако с появлением JavaScript горизонты применения различных операций существен- существенно расширились. Бегущие строки Эффект бегущей строки относится к числу наиболее распространенных в среде разработчиков Web-сайтов. Цель данного эффекта — передать посетителям сайта последние новости или пикантные сообщения. Бегущая строка впервые получила популярность после примене- применения в Java-аплетах. Создание бегущей строки в JavaScript тоже предус- предусматривается, хотя при этом внешний вид ее будет не столь эффективным, как в Java-аплете. Все это объяс- объясняется использованием объекта Text в роли контейне- контейнера для прокручиваемого текста, а ни один из объектов HTML-формы не сможет поразить пользователя своим великолепием. У разработчиков не будет проблем с со- созданием бегущих строк JavaScript, поскольку они не нуждаются в отдельном аплете. Необходимость в таких строках возникает очень часто. Для создания бегущей строки в JavaScript необходимо: Создать HTML-форму с внедренным объектом Text. Записать функцию, прокручивающую текст внутри объекта Text. Ассоциировать функцию с обработчиком событий окна on Load для запуска процесса. Для начала создайте объект Form и внутри него объект Text. При этом рекомендуется соответствую- соответствующим образом назвать эти объекты, поскольку они создаются исключительно для реализации бегущей стро- строки и ни для чего более. Например, форму стоит назвать "marqueeForm", а объект Text — "marqueeText" или как- то по-другому, однако максимально близко по смыслу. После этого необходимо ввести сообщение как атрибут value дескриптора <input>. Ниже приводится код <form>: <CENTER> <form name="marqueeForm"> <input name="marqueeText" size=0" value="THIS JUST IN...JavaScript is selected as official scripting language of the 2000 Summer 01ympics"> </form> </center> После определения контейнера для бегущей строки можно приступить к основной части. Для начала опре- определяются две глобальные константы, используемые в бегущей строке: скорость прокручивания (в миллисе- миллисекундах) и количество знаков, прокручиваемых за опре- определенный временной промежуток. Затем потребуется создать объект String с именем marqueeMessage: var SCROLL_RATE = 100; var SCROLL_CHARS = 1; var marqueeMessage = new String() ; Следующий шаг — создание функции JSMarquee(), придающей обыкновенному объекту Text вид бегущей строки. Поскольку бегущая строка должна постоян- постоянно обновляться, не удастся обойтись без рекурсии JSMarquee() за счет вызова setTimeout() в начале фун- функции. Метод setTimeout() подробно описывается в гла- главе 14. Lflo6aflbHaH переменная SCROLL_RATE исполь-
Технологии программирования на динамическом HTML Часть IV зуется как параметр метода, определяющий частоту вы- вызова функции. Основная задача функции JSMarquee() заключает- заключается в получении значения объекта Text и присвоению его строке marqueeMessage. Затем можно смоделировать перенос слов, отделяя порцию данных сообщения спе- спереди и переписывая эту порцию в конец строки. Для этого используется метод substring() объекта String: function JSMarquee (){ .setTimeout ('JSMarquee {) ' , SCROLL_RATE) ; marqueeMessage = document.marqueeForm.marqueeText.value; document.marqueeForm.marqueeText.value = marqueeMessage. substring ( SCROLL_CHARS ) + marqueeMessage.substring( 0, SCROLL_CHARS ) ; ) На рис. 21.1 показан эффект бегущей строки в мо- момент, когда пользователь находится на странице. Полный исходный код для этого примера приводит- приводится в листинге 21.1. ПРИМЕЧАНИЕ ,, ,, "..'.'', Помимо исходного кода, в листинге 21.1 имеется так- также и дополнительный код JavaScript, поэтому текст сообщения можно определить как глобальную пере- переменную. Так его проще поддерживать при условии частого изменения текста объявления. Баннеры Баннеры — еще один компонент, который часто при- присутствует на Web-страницах. Они привлекают к себе внимание и применяются, в основном, для рекламных целей. Обычно их миссия состоит в том, чтобы заинт- заинтриговать пользователя и заставить его щелкнуть мышью именно в этом месте. Используя объекты Image, мож- можно создавать профессиональные баннеры, обходясь без анимированных GIF-изображений или Java-аплетов. ^ПРИМЕЧАНИЕ ''.'¦'.- ' *? Перед созданием самого сценария потребуются два набора GIF-файлов одинаковых размеров. Необходимы два или три изображения, которые после будут слу- служить как главные изображения баннера. Для достиже- достижения эффекта перехода потребуется серия переходных изображений. Изображения, в случае их последова- последовательной отрисовки, будут выглядеть подобно анимации. Для создания удобоваримого эффекта достаточно будет и пяти-шести переходных изображений. Следите за общим размером GIF-файлов. Некоторые пользователи, загружая страницу с 15 GIF-изображе- GIF-изображениями на скорости соединения 28,8 Кбайт/с могут и не оценить ее. Как только GIF-файлы готовы, можно приступить к созданию баннера в JavaScript: Листинг 21.1. Реализация бегущей строки с использованием JavaScript <html> <head> <title> JavaScript Unleashed</title> <script type="text/javascript"> <! — // объявление переменных var SCROli_RATE = 100; var scroll_chars = 1; var MESSAGE = "THIS JUST in. . .JavaScript is selected as ¦¦ + "official scripting language of the 2000 Summer Olympics..." var marqueeMessage = new String () ,- function JSMarquee () [ setTimeout( ¦JSMarquee{)', SCROLL_RATE ) ; marqueeMessage = document.marqueeForm.marqueeText.value; document.marqueeForm.marqueeText.value = [ marqueeMessage. substring;( SCROLt._CHARS ) + marqueeMessage.substring( 0, SCROLL_CHARS >; J </script> </head> <body onload="JSMarquee()"> <center> <form name="marqueeForm"> <input name="marqueeText" size=0"> <script type="text/javascript"> <! — document. marqueeForm. marqueeText. value = MESSAGE; II—> </script> </form> </center> </body> <)html>
Визуальные эффекты 1. Создайте заглушку для изображения на Web-стра- Web-странице. 2. Определите массив для хранения исходных изоб- изображений и для хранения переходных изображений. 3. Создайте программу для управления презентацией изображений. 4. Определите эту функцию в качестве обработчика событий onLoad. p H3~offlciai BtftipClng РИСУНОК 21.1. Пример бегущей строки Для начала создайте на Web-странице объект Image, который послужит заглушкой для всех действий. По- Поскольку баннер переносит куда-то в другое место, как только на нем совершается щелчок, очевидно, дескрип- дескриптор <img> потребуется поместить внутрь ссылки: <а href = "http://www.mcp.com" onmouseover="window. status='http:// '-•www.mcp . com1 ¦ return true;" onmouseout="window.status = ' ' ; return true;"> <img name="billboard" height=9" width=33" src=" ./visjs .gif"> .¦ПРИМЕЧАНИЕ Обратите внимание на обработчики событий onMouseOver и onMouseOut, определенные в объекте Link. Без них можно обойтись, если URL закодирован жестко. Эти обработчики необходимы в случае, если с каждым ис- исходным изображением в баннере связаны различные адреса URL. В таком случае потребуется предусмот- предусмотреть массив URL и текст mouseOver, зависящий от ак- активного изображения. Внутри раздела <head> поместите дескриптор <script> и определите набор переменных и объектов. Две гло- глобальных константы хранят время (в миллисекундах) для Глава 21 отображения основного и переходного изображений. Две дополнительные переменные определяются позже: .// Глобальные константы var DISPLAYJTIME = 3500; var TRANSITIONJTIME = 50; .// Глобальные переменные var primaryldx = О; var transldx = 0 ; Потребуется определить два массива для хранения информации о наборах начальных и переходных изоб- изображений. Для каждого элемента массива объявляется свойство изображения scr. // Первый массив содержит начальные изображения JSBillboardArray = new Array ( 3 ) ; JSBillboardArray[0] = new Image ( 49, 333 ; JSBillboardArray[0].src = "./visjs.gif"; JSBillboardArray[1] = new Image ( 49, 333 ) JSBillboardArray[1].src = "./url.gif"; JSBillboardArray [2] = new Image ( 49, 333 ) ; JSBillboardArray[2].src = "./bltwith.gif"; // Второй массив содержит // изображения transArray = new Array ( 6 transArray [0] = new Image ( transArray[0].src = "./bw7 transArray[1] = new : transArray[1].src = transArray[2] = new transArray[2] .src = new transArray [3] .. src = transArray [4] = new transArray [4] ,. src ¦ — new transArray[5J . src = /bw6 Image ( "./bw5 Image( " . /bw4 Image ( •' . /bw3 Image( 11. /bw2 переходные 49, 333 ) , •gif"; 49, 33 1 ) .gif"; 49, 333 ¦ .gif"; 49, 333 ] .gif"; 49, 333 .gif"; 49, 333 .gif"; Главной функцией, которая используетсядля запус- запуска баннера, является runJSBillboard(). Сначала она оп- определяет интенсивность изменения каждого цикла ото- отображения баннера. Затем это значение применяется для вызова рекурсивного метода setTimeout(). В конечном итоге функция runJSBillboardO вызывает вторую фун- функцию repaint (): function runJSBillboardO { changeRate = DISPIAY_TIME + ( transArray. length * TRANSITIONJTIME ) ; setTimeout( "runJSBillboardO" , changeRate ); repaintO ; Функция repaint() является основой баннера в. JavaScript. Она определяет изображение, выводимое на экран в данном цикле. Первые на очереди — переход- переходные изображения. Далее на арену выходит функция repaint(), которая проверяет их состояния и определя- определяет, должен ли завершиться цикл. Если это действительно так, активизируется раздел кода if, выводящий на экран
Технологии программирования на динамическом HTML Часть IV текущее начальное изображение. В противном случае в действие вступает раздел кода else: function repaint () ( if ( transldx > transArray. length - 1 ) { primaryldx-H- ; transldx = 0 ; if ( primaryldx > JSBillboardArray. length - 1 > primaryldx = 0; document.billboard.src = JSBillboardArray[primaryldx].src; return; )else{ document.billboard.src = transArray[transldx],src; setTimeout( "repaint()", TRANSITIONJTIME ) ; } transldx++; Функция repaintO заслуживает чуть большего вни- внимания. Раздел if предназначен для вывода на экран на- начального изображения, в особенности того, что является текущим в JSBillboardArray. Если это условие выполня- выполняется, переменная transldx получает значение 0. В сле- следующий раз переходный цикл начинается с repaint(). Необходимо проверить, возвратилась ли в исходное со- состояние primaryldx и вернуть управление вызывающей Функции runJSBillboard(). Благодаря рекурсивному характеру runJSBillboard, функция repaintO сразу же выполняется заново. В пос- последний раз обрабатывался раздел if, теперь можно и не сомневаться, что в этом цикле выполнится раздел else. Этот раздел кода выводит на экран текущее переходное изображение из массива transArray. else запускается при каждом переходном цикле, пока не будет выводится последнее переходное изображение. В следующий раз вызывается repaintO. if возвращает в начальное состоя- состояние все, что уже выполнялось. ПРИМЕЧАНИЕ Рекурсия относится к достаточно сложным принципам программирования. Тем не менее, как видно из пос- последнего примера, она отличается существенной мо- мощью и изяществом. На рис. 21.2 и 21.3 показаны экраны во время цик- циклического процесса вывода баннера. В листинге 21.2 предоставлен полный исходный код реализации вывода баннера. Листинг 21.2. Создание доски объявлений с использованием JavaScript <html> <head> <title>JavaScript Unleashed</title> <script type="text/javascript" languages"JavaScriptl.1"> / / Глобальные константы var BB_URL = 'http://www.mcp.com'; var DISPIAYJTIME = 3 500; var TRANSITioNJTIME = 50; ./ / Глобальные переменные var primaryldx = 0; var transldx = 0; // Первый массив содержит основные // изображения JSBillboardArray = new Array ( 3 ) ; JSBillboardArray [0] = new Image ( 49, 333 ) ; JSBillboardArray[0].src = "./visjs.gif"; .JSBillboardArray [1] = new Image ( 49, 333 ) ; JSBillboardArray[1] .src = "./url.gif " ; JSBillboardArray [2] = new Image ( 49, 333 ) ; JSBillboardArray [2] . src. = " . /bltwith. gif" ; // Второй массив ,содержит переходные // изображения transArray = new Array ( ) ; transArray [ 0 ] = new Image ( ,49, ;,K3 ) ,- transArray [0] .src «: ". /bw7-.gif "; transArray [ 1 ] i= new Image ( 49 „ 333 ) ; transArray [1] .src ¦ "./bw6..gif";. transArray [2] = new Image ( 49, 333 ) ; transArray [2] .src ¦ " . /bw5 ,.gif".; transArray [3 ] = new Image ( ,.1.3, 333 \ ; transArray [3] .src " "./bw4..gif"; transArray [ 4 ] = new Image ( 49, 333 ) ; transArray [4] .src = '". /bwS.gif"; transArray [5] = new Image ( 49, 333 ); transArray [5] . src ¦ " . /bw2.gif"; function runJSBillboard О { changeRate = DISPIAYJTIME + (transArray. length * TRANS ITION_TIME); setTimeout("runJSBillboard 0 ", changeRate); repaintO ; function repaintO { if (transldx > transArray. length - 1) ( primary Idx++; // Увеличить индекс // первичного изображения transldx =0; // Сбросить индекс // переходного изображения if (primaryldx > JSBillboardArray.length - 1){ primaryldx =0; // Сбросить // индекс первичного изображения ;t document.billboard.src = JSBillboardArray[primaryldx].sic; return; // Возврат в run JSBillboard () }else{ // Отобразить переходное изображение document.billboard.src = transArray[transldx].src; // Рекурсивный вызов repaintO в // цикле setTimeout( "repaint()", TRANSITION TIME ) ; i transldx++; Увеличить индекс переходного изображения
Визуальные эффекты </soript> </head> <body onload="runJSBillboard() "> <center> <a href ="http: //www.mcp.com" onmouseover="window.status=BB_URL; return true;" oranouseout="window. status return true;"> <img name="billboard" height=9" width=33" src=" . /visjs .gif </a> </center> </body> </html> i РИСУНОК 21.2. Начальное основное изображение Б . ( .v::.V-^:>,^ .v:;t;b .. ..-,: ¦:- РИСУНОК 21.3. О из пяти переходных изображений Постепенное изменение цветов В данной главе рассматривались вопросы создания бан- неров и прокручиваемых объявлений наподобие, Java- аплетов. Не обращайте внимание на "очковтиратель- Глава 21 ство", которое встречается в прессе: мол, Java может не все. Дело здесь связано с одним лишь моментом — по- постепенным изменением цвета на HTML-странице. JavaScript может управлять HTML-документом, чего не делает Java. Именно поэтому JavaScript работает с подоб- подобного рода методами гораздо лучше. РИСУНОК 21.4. Второе основное изображение Постепенное изменение цвета выполняется при посте- постепенном изменении значения свойства bgColor объекта Document. Данное свойство является либо шестнадца- шестнадцатиричным RGB-триплетом, либо строковым литералом, представляющим RGB-триплет, например, "aqua" или "red". Несмотря на простоту работы со строковыми ли- литералами, при условии установки свойства bgColor на единовременной основе, потребуется использовать ше- шестнадцатиричные значения RGB-триплетов в формате rrggbb. В JavaScript можно создать функцию JSFade(), ко- которая будет выполнять смену цвета, а затем обратиться к этой функции во время загрузки документа. Функция JSFade() получает несколько параметров. Начальные значения RGB для красной, зеленой и си- синей составляющих цвета. •• Конечные значения RGB для красной, зеленой и си- синей составляющих цвета. Количество миллисекунд, необходимых для выпол- выполнения процесса смены цвета. Цикл for используется для пошагового выполнения процесса. Именно с помощью параметра задержки мож- можно определить, сколько раз сработает цикл for. Опреде- Определяются две переменные: finishPercent — указывает на процентную часть оставшегося процесса, startPercent — указывает на процентную часть выполненного процес- процесса. Основой выполнения смены цвета является приве-
Технологии программирования на динамическом HTML Часть IV денный ниже оператор, который присваивает значение свойству document.bgCoIor. Значение базируется на сум- сумме произведений начального значения красного на пе- переменную startPercent и конечного значения красного на переменную finishPercent. Эта же операция повторя- повторяется также для зеленого и красного цветов. function JSFade(startRed, startGreen, startBlue, finishRed, finishGreen, finishBlue, delay){ for (var i = 1; i <= delay - 1,- i++) { var flnishPercent = I/delay; var startPercent = 1 - flnishPercent; document.bgColor = Math.floor(startRed * startPercent + finishRed * finishPercent) * 256 * 256 + Math, floor (startGreen * startPercent + finishGreen * finishPercent) * 256 + Math.floor(startBlue * startPercent + finishBlue * finishPercent ) ; Затем эту функцию можно вызвать в собственном сценарии. Например, для реализации смены от цвета белой ночи к бирюзовому, потребуется выполнить та- такой вызов: JSFade B55,255,2400,128,128,170) Переход цвета от синего к красному: JSFade @,0,198, 196,2,40,170) От черного к белому: JSFade @,0,0,255,255.255,170) В листинге 21.3 представлен исходный коддля при- примера смены цветов. Листинг 21.3. Использование JavaScript Анимированные командные кнопки За последние три года восприятие Web существенно изменилось. Изначально задуманная кактекстово-ори- ентированная среда передачи информации, Web сегод- сегодня работает с графикой, мультимедиа-информацией и сложными страницами. Однако, единственным аспек- аспектом устаревшего нелицеприятного вида остались объек- объекты форм, например, текстовые поля ввода и командные кнопки. Для этих управляющих элементов управления, невозможно даже выбрать шрифт. Неудивительно, что в настоящий момент многие раз- разработчики обращаются к JavaScript с целью обеспече- обеспечения альтернативы одному из общих элементов управле- управления пользовательского интерфейса — кнопкам. Хотя объекты графических кнопок пока еще не доступны, с помощью объекта Image в JavaScript можно сымитиро- сымитировать их поведение. ПРИМЕЧАНИЕ \, J,.,.; . ;,.,,. , s J Так же, как и в примере с баннерами, необходимо сначала подготовить подходящие GIF-файлы для исполь- использования на Web-странице. Сейчас будет показано, как применить JavaScript для эмуляции вида и формы кнопок в Windows 98/2000, что впервые появилось в Microsoft Internet Explorer 3. Кнопка имеет плоский вид, пока пользователь не наве- наведет на ее указатель мыши, после чего она приобретает трехмерный вид. Давайте добавим на страницу кнопки Previous и Next, эмулирующие кнопки Prev и Next бра- браузера. для смены цвета фона документа _ <html> <head> <title>JavaScrip Unleashed</title> <script type="text/javascript"> <! — function JSFade (startRed, startGreen, startBlue, finishRed, finishGreen, finishBlue, delay) { for (var i = 1; i <= delay - 1; i++) { var finishPercent = i/delay; var startPercent = 1 - finishPercent; document. bgColor = Math, floor (startRed * startPercent + finishRed * finishPercent) * 256 * 256 + Math, floor (startGreen * startPercent +finishGreen * finishPercent) * 256 + Math, floor(startBlue *startpercent + finishBlue * finishPercent ); I </script> ¦</head> <body> <script type="text/javascript"> < i JSFade( 255,255,240,0,128,128,170 ) ; ,11—> </script> </body> </html>
Визуальные эффекты Для создания анимированных кнопок потребуется проделать следующее: Создать заглушки для изображений на Web-страни- Web-странице под каждую кнопку. Определить объекты Image и поставить им в соот- соответствие GIF- и JPG-файлы. Создать программу для вывода изображений на эк- экран по запросу. Добавить код обработчика событий click для объек- объекта Link. Для использования объектов Image в качестве заме- заменителей кнопок потребуется определить дескрипторы <img>. Однако, поскольку объекты Image не способны реагировать на события, каждое изображение следует поместить в объекте Link: <а href=""> <img src=" . /prev_off.gif" border=" width=2" height=2" name="prev"> <a href=""> <img src=" ./next_off.gif" border=" width=2" height=2" name="next"> Внутри дескриптора <script> раздела <head> HTML-документа необходимо определить объекты Image для каждого из четырех используемых изображе- изображений: два, представляющих плоский вид кнопки, и два, представляющих трехмерный вид кнопки. Также объек- объекты Image потребуется связать со внешними файлами: var prevBtnOff = new Image ( 42, 52 ) ; prevBtnOff.src = "./prev_off.gif"; var prevBtnOn = new Image ( 42 , 52 ); prevBtnOn.src = ''./prev_on. gif" ; var nextBtnOff = new Image ( 42, 52 ) ; nextBtnOf ?. src = "./next__off.gif"; var nextBtnOn = new Image ( 42, 52" ) ; nextBtnOn,src = "./next_on.gif"; Итак, заглушки в виде дескрипторов <img> для кно- кнопок Previous и Next определены, а экземпляры объек- объектов Image для состояний "off и "on" созданы. Следующий шаг заключается в добавлении функции high]ightButton(), которая изменяет состояние изображения, выводимого на экран по запросу. Функция highlightButton принимает два параметра: первый — это имя шаблона изображения <img>, а вто- Листинг 21.4. Анимированные кнопки в JavaScript. Глава 21 рой — это имя объекта Image, выводимого на экран. Для ссылки на заглушки изображений <img> можно вос- воспользоваться встроенным массивом document.images. function highlightButton{placeholder, imageObject) { document. images [placeholder] . src = eval (imageObject + ",src") ] Сейчас необходимо вернуться к определениям дес- дескриптора <img> и добавить в них код соответствующе- соответствующего обработчика событий. Планируется, что при наведе- наведении указателя мыши на две анимированные кнопки, они приобретут трехмерный вид, имея до этого плоский вид. Для этого потребуется добавить обработчики событий onMouseOver или onMouseOut. При поступлении собы- события onMouseOver вызывается функция highlightButton() для данной кнопки. Затем, когда генерируется событие onMouseOut, вновь вызывается функция highlightButton(), которая обеспечит отображение выключенного состоя- состояния кнопки: <ahref="javascript:history.back(> " onmouseover="highlightButton С'Prev', 'prevBtnOn'); window. status= " Previous ' ; return true; " onmouseout="highlightButton( "Prev', 'prevBtnOff' ) ; window . status= ' 1 ; return true; "> <img src=" . /prev_off.gif" border=" width=2" heights2" name="Prev"> <a href="javascript:history.forwardO" onmouseover="highlightButton( 'Next', 'nextBtnOn'); window. status= ' Next ' ; return true; " onmouseout="highlightButton( ' Next" , ' nextBtnOff ' ) window.status=' ' ;return true;"> <img src=" ./next_off.gif" border=" width="S2" height=2" name="Next"> Последний шаг связан с добавлением кода, который реагирует на нажатие анимированной кнопки. Посколь- Поскольку объект Image не отвечает на событие click, следует использовать протокол javascript: в свойстве href объек- объекта Link. Как показано в предыдущем коде, требуемую функциональность обеспечивают методы back() и forward () объекта History. Наконец, потребуется добавить код в обработчики событий onMouseOver и onMouseOut, который обеспе- обеспечит вывод соответствующего сообщения в строке состо- состояния браузера. На рис. 21.5 и 21.6 показан код в действии. В листинге 21.4 приводится полный исходный код. <html> ¦<head> <title>JavaScript Unleashed</title> <script type="text/javascript" language="JavaScriptl . // Определение объектов изображении
Технологии программирования на динамическом HTML Часть IV var prevBtnOff = new Image D2, 52) ; prevBtnOff.src = "./prev_off.gif"; var prevBtnOn — new Image D2, 52); prevBtnOn.src = "./prev on.gif"; var nextBtnOff = new Image D2, 52); nextBtnOff.src = "./next_off.gif"; var nextBtnOn = new Image D2, 52); nextBtnOn, src = "./next__on.gif"; // Изменение изображения, выведенного на экран function highlightButton(placeholder, imageObject) { document.images[placeholder].src = eval(imageObject + </script> </head> <body background=" ,/aiback.gif"> <center> <a href="javascript; history.back() " retur true; onmouseout="highlightButton ( 'Prev', 'prevBtnOff ) ; window, status=' ' /return true ;"> <img src=" . /prev_off.gif" border=" width=2" height=2" name="Prev"> <a href="javascript:history. forward)) " onmouseover="highlightButton( 'Next1, 'nextBtnOn') ; window, status= ' Next' ; return true onmouseout="highlightButton ( 'Next' , 'nextBtnOff'); window, status= ' ' ;retuj:n true;"> <img src=" . /next_off.gif" border=" width="! </center> </body> </html> РИСУНОК 21.5. Кнопки в стандартном начальном состоянии. Резюме Давайте посмотрим правде в глаза: многие Web-сайты скучны и совсем не привлекают внимания. Сам по себе HTML не может сделать ничего более лучшего, нежели просто поместить плоское изображение на страницу и вывести его на экран. Для придания большей живости HTML многие разработчики используют Java-аплеты. РИСУНОК 21.6. Кнопка Previous приобретает трехмерный вид, когда на нее наводится указатель мыши. По мере развития JavaScript, все больше и больше про- программистов отдают предпочтение этому языку. В JavaScript 1.1 и 1.2 появились новые возможности совершенствования внешнего вида Web-сайта. В этой главе рассматривались четыре наиболее ПОГ способа создания спецэффектов с использованием JavaScript: бегущие строки, баннеры, анимир! кнопки и постепенное изменение цвета.
Каскадные таблицы стилей В ЭТОЙ ГЛАВЕ Основные концепции таблиц стилей Использование стилей в документах Объекты стилей в JavaScript Появление каскадных таблиц стилей (CSS) в HTML дало разработчикам возможность акцентировать внима- внимание на стиле, совершенствовать внешний вид докумен- документов и определять для них более совместимые стили. Перед появлением CSS одним из главных недостатков публикации информации в Web было отсутствие воз- возможности управления существующими в тот момент настольными издательскими средствами. Необходимо было придумывать различные обходные пути, чтобы все элементы располагались в правильных местах, а шриф- шрифты были необходимого размера и вида. Для расположе- расположения элементов в нужном порядке разработчики зачас- зачастую прибегали к HTML-таблицам, однако сбои в работе браузеров сводили на нет все старания. Весь этот кошмар закончился, когда CSS стали ре- рекомендацией на Консорциуме World Wide Web (W3C). CSS помогли разработчикам точно устанавливать шриф- шрифты, размеры текста и расположение элементов (CSS positioning, CSS-P). В главе рассматриваются CSS, а также массивы Navigator, позволяющие работать со стилями. Это не значит, что будут исследоваться буквально все аспекты CSS. Дабы упростить чтение глав 23 и 24 (посвящен- (посвященных динамическому HTML), приводятся только самые главные характеристики. «примечание' ."'¦ ¦"; ,. ';¦':'. В этой книге не предусмотрено подробное рассмот- рассмотрение CSS. Исчерпывающее описание CSS может быть найдено на сайте: http://www.w3.org. Основные концепции таблиц стилей Таблица стилей состоит из одного и более параметров (размер шрифта, стиль шрифта, выравнивание текста, цвет шрифта и фона, границы, заполнение, высота строк и т.д.) элементов HTML, которые могут быть связаны или внедрены в HTML-документы. Данная функция обеспе- обеспечивает для Web-дизайнеров возможность четко устанав- устанавливать стиль и расположение по всему документу. На протяжении следующих нескольких страниц производится знакомство с этой технологией и расска- рассказывается, как применить ее в JavaScript. Кроме того детально описывается методика использования CSS, поскольку они являются неотъемлемой частью данной технологии. Стандарты Для широкомасштабного внедрения любого вида техно- технологии необходимо определиться со стандартами или формализованными методами реализации. CSS вместе со многими стандартами, используемыми на сегодняш- сегодняшний день, поддерживается Консорциумом World Wide Web (W3C). Рассмотрим коротко рекомендацию CSS. CSS Level 1 (Уровень 1 CSS) В декабре 1996 г. первая версия CSS приобрела офици- официальный характер в W3C. Это была первая попытка со- создания стандартного метода применения стилей в Web- документах. Такой прогрессивный шаг открыл для разработчиков новые возможности по усовершенствова- усовершенствованию документов. Однако, даже последние обновления рекомендации в январе 1999 г. не содержали достаточных вещей, не- необходимых разработчику (таких как способность распо- располагать элементы на странице). Кроме того, в ней не учи- учитывались портативные и беспроводные устройства.
Технологии программирования на динамическом HTML Часть IV CSS-P В августе 1997 г. W3C выдал рекомендации по позици- позиционированию при помощи каскадированых таблиц сти- стилей (CSS-P). Рекомендация содержала набор свойств,, позволяющих разработчикам открыто определять распо- расположение элементов на странице. В комбинации с CSS все это существенно усилило управление над минималь- минимальными частицами изображения, обеспечив возможность создания стильных страниц. Комбинации CSS1 и CSS- Р были впервые внедрены в браузеры Navigator 4, Internet Explorer 4 и Opera 3.5. Level 2 Enhancements (Усовершенствования уровня 2) Вторая версия рекомендации CSS, CSS Level 2 или, для краткости, CSS2 может выполнять дополнительные операции. Во-первых, рекомендации CSS1 и CSS-P были объединены в отдельную рекомендацию. Была ре- реализована концепция медиа-типов, что больше соответ- соответствовало требованиям стилизации печатного материала. Добавилось понятие данных, необходимыхустройствам доступа к Internet. Плюс ко всему, в CSS2 была введена спецификация вида курсора или указателя для указа- указательных устройств. Предложения по поводу Level 3 Группа CSS консорциума W3C на данный момент ра- работают над уровнем 3 — CSS Level 3 (CSS3). Эта после- последняя разработка пока еще не готова. В ней предусматри- предусматривается не только поддержка масштабируемой векторной графики и интернационализации, но также и ряд усо- вершенствованийпользовательского интерфейса. Имен- Именно данная версия должна больше всего приблизить CSS к глобально поддерживаемой рекомендации. Подобное влияние HTML 4 оказал на HTML. Наследование При определении стилей необходимо помнить о кон- концепции наследования. Термин наследование (inheritance) используется для обозначения процесса передачи свойств от родительского элемента к дочернему. Поня- Понятия родительский (parent) и дочерний (child) элементов относятся к HTML-элементам. Они группируются внут- внутри других элементов. Таблицы стилей позволяют уста- устанавливать глобальный стиль для документов, а также обеспечивают возможность передачи стилей другим эле- элементам внутри элементов, таким образом сокращая вре- время на определение стиля для каждого из элементов. Например, внутри элемента <body> могут находиться дочерние элементы, включая <Ы> и <р>, внутри ко- которых содержится еще некоторое число дочерних эле- элементов (например, <ет>). Стиль родительского эле- элемента наследуется дочерними элементами, если у последних присутствуют какие-то свойства. Несложно убедиться, что <р> внутри <body> получит размер шрифта <body>, если только в <р> он не будет заме- заменен. Стили наследуются внутри контейнеров, для ко- которых они определяются. Эта способность обеспечива- обеспечивает необходимый вид и форму документа. Размеры шрифта, размещение текста, границы - наглядные примеры того, как таблицы стилей придают Web-сайту большую логичность и последовательность. За счет определения стилей глобально внутри родитель- родительских элементов происходит их наследование дочерни- дочерними элементами документа. Все документы могут иметь одинаковый вид, пока у разработчика есть возможность управления стилями и их замены во время рабочего се- сеанса. .ПРИМЕЧАНИЕ :v i= v"Pc ; . , . Z> ¦*¦> Очень часто встречаются не унаследованные стили. Если свойства порожденного объекта отличаются от свойств исходного объекта, стиль наследоваться не должен. Границы и заполнение текста пробелами С помощью CSS можно определить границы, обрамле- обрамление и заполнение текста пробелами для элементов блоч- блочного уровня. Элементы блочного уровня — это такие элементы, как <hl>, <р>, которые всегда начинаются с новой строки. Эти свойства позволяют задавать раз- различные элементы, начиная с границ и завершая обрам- обрамлением. Комментарии Далеко не каждый код может обойтись без коммента- комментариев. Написание комментариев в CSS напоминает оп- определение комментариев в других языках программиро- программирования, за исключением тех, что поддерживают общеизвестные многострочные комментарии. Напри- Например, /* комментарий типа 1*/ вполне приемлемый формат комментария в CSS. Использование стилей в документах Существует множество различных методов использова- использования стилей в документах. Их можно встраивать, исполь- используя атрибут style внутри секции <style>, или присоеди- присоединять, используя дескриптор <Iink>. Кроме методов определения стилей в документе, существуют и спосо- способы их применения. Стили можно применять глобаль- глобально, присваивая класс с атрибутом class или на индиви- индивидуальной основе при помощи атрибута id.
Каскадные таблицы стилей Глава 22 Определение стилей Как упоминалось ранее, стили можно определять одним из трех способов. Под словосочетанием "определение стилей" подразумевается три расположения стилей. Эти методы определения стилей применяются при создании документа, использующего таблицы стилей. Определен- Определенного способа выполнения данной операции не суще- существует. Постарайтесь решить эту задачу как можно бо- более практично. <style> Первое размещение определяемого стиля — внутри дес- дескриптора <style>. Этот дескриптор принимает един- единственный атрибут (type), сообщающий браузеру о виде определяемого стиля. Значением данного атрибута для CSS является text/ess. Между открывающим и закры- закрывающим дескрипторами находится определение стиля. В примере показаны четыре различных стиля, которые применялись к основной текстовой части документа. Рисунок 22.1 демонстрирует результат загрузки в брау- браузер. Не переживайте по поводу существования различ- различных стилей; этот вопрос будет рассматриваться позже. | G*tttt, it з« ;, wtdspauii J^ tfi J Point size of24 Here is some CAP1TAUJ text РИСУНОК 22.1. Изменение класса для заголовка текста Листинг 22.1. Определение стилей в дескрипторе <style> <html> <head> <style type="text/css"> Ы{ color: green; font-style: italic- font-size: 12pt; \ font-size: 24pt; . newheader{ color: yellow/ #caps< font-variant: small-caps; </style> </head> <body> <hl>Green, italic, and a point size of 12</hl> <hl class="newheader">Yellow, italic, and a point size of 12</hl> <hl class="special">Point size of 24</hl> <P> Here is some <span i.d="caps ">capitalized </span> text. </body> </html> hi.special { <ltnk> Если пользователь желает, чтобы стили хранились или устанавливались в едином местоположении, а измене- изменения выполнялись глобально по всей странице, необходи- необходимо использовать элемент <link>. Он выполняет функ- функцию связывания внешних таблиц стилей и помещение их в документ. Атрибуты элемента <link> (type и href)' используются для определения типа связи и URL, по которому размещается внешняя таблица стилей. Внешние таблицы стилей аналогичны CSS, опреде- определенным внутри документа. Таблица стилей хранится по конкретному URL-адресу. HTML-элементы <style> и </style> в данном случае не нужны. Этот элемент дол- должен содержаться в разделе <head>. В следующем при- примере будет показано, как включать таблицу стилей chapters.css в документ: <head> <link rel="stylesheet" type="text/ess" href="http://www.mcp.com/stylesheets/ chapters.css"> </head> Атрибут style Последний метод определения стилей и включения их в документ связан с использованием атрибута style лю- любого текстового элемента HTML. Атрибут style приме- применяется для определения нового стиля, используемого только для определенного элемента экземпляра. Это обеспечивает возможность каждому элементу обладать своим собственным стилем, независимым от других оп- определенных сталей текущей таблицы стилей. С низкого уровня включает в себя определение J для конкретного экземпляра элемента. С
Технологии программированияна динамическом HTML Часть IV color: yellow; #myid{ font-size: 12pt,- </style> </head> <body> <hl>Green</hl> <hl class="newheader" id="myid">Yellow and point size 12</hl> <hl class="newheader">Yellow and <span id=" ital" >italic</ spanx/hl> <h2>This will be default text<h2> </body> </html> Определение старшинства стиля Чтобы определиться со значением или старшинством стиля элемента либо свойства, необходимо придержи- придерживаться следующих правил: 1. Размещайте все ссылки на элемент с помощью се- селекторов., 2. Сортируйте ссылки с использованием явных весов. 3. Сортировка должна выполняться от корня таблицы стилей. Значения по умолчанию заменяются поль- пользовательскими таблицами стилей, а те, в свою оче- очередь, — авторскими таблицами стилей. 4. Производите сортировку по специфичности. Рядом с каждым из трех вариантов поставьте очко, а затем сложите очки, чтобы получить специфичность: Количество атрибутов id. Количество атрибутов class. Количество имен дескрипторов, на которые осу- осуществлялись ссылки. 5. Выполняйте сортировку по порядку специфичнос- специфичности. Из двух правил, одинаковых по весу, преиму- преимущественным будет последнее. Объекты стилей в JavaScript JavaScript 1.2 были введены три новых объекта — tag, class и id. Они используются в таблицах стиля Эти объекты применяются для определения типов сталей "тили можно определить как во внешних таблицах сти- стилей, связанных с HTML-документами, так и в самом документе внутри дескрипторов <style> и </sty!e> ? ПРИМЕЧАНИЕ "* другие браузеры могут поддерживать или не поддер- поддерживать действия этого метода, обязательно примите решение относительно использования этих дескрипто- дескрипторов для присваивания стилей. document.tags На данный момент только Массив document.tags — это ссылка на дескрипторы HTML; в действительности, он является подобъектом объекта Document. После определения следует элемент, к которому применяется данный массив. За элементом расположено описание, которое является уже опреде- определенным свойством стиля (имя которого не всегда совпа- совпадает с именем, определенным в CSS). Синтаксически все дескрипторы <р> должны иметь размер шрифта в 20 пунктов: document, tags -p. fontSize = 0pt" ; document.classes document-classes -- массив и подобъект объекта Document. В данном массиве имеется доступ к дескрип- дескрипторам со специальным атрибутом class. Класс стилей используется для одного элемента: document.classes.fontclass.blockquote.fontSize =  Opt"; Или же он может быть доступен для всех элементов: document.classes.fontclass. all.fontSize = 0pt"; За объектом в точечной нотации следует имя клас- класса, а затем элемент, для которого определяется класс. Классы, определяемые как а», можно применять ко всем элементам, что продемонстрировано во втором при- примере. document.ids Объект document.ids напоминает document.classes, раз- различие состоит лишь в том, что некоторые элементы относящиеся к id, визуализируются с использование1 определенного стиля. document.ids.myid.fontSize = 0pt"; За дескриптором объекта document.ids следует им id и, в отличии от объектов document.classes и docHfiiemltags, оно не воспринимает имя элемента как часть ОПр:деле- ния. Объекты document.ids используются вместе: эле- элементами, к которым применяются. Свойства В табл. 22.1 приводятся СВОЙСТВА, ХЗОМШЙП ш объектов стилей JavaScript. М№ЩШ Ш
Таблица 22.1 Имя свойства .Свойства объектов стилей К чему применяется JavaScript Возможные значения каскаоные таблицы стилей ЕТ!П Глава 22 Ш1 Определение значений fontSize IborderS tyle width length align color backgroundlmage backgroundColor display listStyleType whiteS pace Все элементы Свойства шрифта Абсолютные размеры Относительные размеры Процентость fontStyle lineHeight verticalAligm text Decoration textTransform textAlign textlndent paddings() borderWidthsQ imarginsf) Все элементы Элементы блочного уровня Все элементы Все элементы Все элементы Элементы блочного уровня Элементы блочного уровня Все элементы 'Все элементы Все элементы Свойства текста Число Длина Процентость Длина Процентность Свойства блочного уровня Число Процентность Число Длина Процентность Автоматизация Свойства блочного уровня Все элементы Элементы блочного уровня Длина Процентность Автоматизация Элементы блочного уровня Длина Автоматизация Все элементы Все элементы Все элементы Все элементы Свойство цвета Цвет Цвет Классификационные свойства Все элементы Элементы со свойством display Элементы блочного уровня Normal и рге x-small, small, medium, large, x-large, размер в пунктах smaller, larger На 150% больше normal, italic, oblique, small-caps Количество единиц для увеличения высоты Абсолютное значение высоты линии Процент от родительского элемента baseline, sub, sup, top, text-top, middle, bottom, text-bottom none, underline, overline, line-through, blink capitalize, uppercase, lowercase, none left, right, center, justify Количество единиц для отступа Процент от родительского элемента Количество единиц для заполнения Процент от родительского элемента Количество единиц для ширины рамки Границы в единицах Процент от родительского элемента Документ автоматически определяет границы шопе, solid, 3D Ширина в единицах Процент от родительского элемента Документ автоматически определяет ширину Длина в единицах Документ автоматически определяет длину left, right, none Имена цветов, цвета RGB. URL Имена цветов, цвета RGB. block, inline, list-item, none disc, circle, square, decimal, lower-roman, upper-roman, lower-alpha upper-alpha, none
Технологии программирования на динамическом HTML Часть IV Резюме Появление таблиц стилей предоставило разработчикам большие возможности по управлению внешним видом документов. Можно определять стили по умолчанию внутренне и внешне, и применять их ко множеству эле- элементов. В настоящий момент доступно большое коли- количество свойств стилей, что позволяет разработчикам взять под полный контроль внешний вид содержимого.
Слои В ЭТОЙ ГЛАВЕ Универсальные действия <div> и <iframe> <1ауег> и <ilayer> До недавнего времени одним из фундаментальных ограничений Web-страниц была невозможность распо- расположения текста или изображений точно в указанном месте на странице. Кроме того, не существовало спосо- способов наложения HTML-элементов друг на друга. Один из наиболее полезных в плане творчества аспектов но- новых браузеров — поддержка слоев. Слои (layers) позво- позволяют создавать накладывающиеся прозрачные или непрозрачные элементы с содержанием в HTML-доку- HTML-документе, которые вдобавок можно устанавливать точно в указанном месте. Слои реализуются с помощью несколь- нескольких различных методов, и те, кто хорошо знаком с из- издательским миром Web, знают, что именно это чаще всего приводит в замешательство. В мире вне браузера Navigator 4 слои создавались с использованием HTML-дескриптора и многократного применения свойств позиционирования таблицы стилей (CSS). отображения и управления порядком располо- расположения дескрипторов. По своей природе дескриптор <div> (разделение данных) был логически наиболее подходящим для создания слоев, и именно его обычно использовали. Теперь существует Navigator 4, который был выпущен с набором программ инструментальных средств для Internet Netscape Communicator в 1997 г. Navigator 4 содержит два новых дескриптора: <1ауег> и <ilayer> ("i" обозначает inflow — внутрипотоковый). Эти дескрипторы предоставили различные пути от стандар- стандартного использования дескрипторов <div>, которые под- поддерживает Navigator, до создания слоев в HTML-доку- HTML-документе. В отличие от дескриптора <div>, дескрипторы <1ауег> и <ilayer> имеют атрибуты, которые, в сущно- сущности, позволяют "стилизировать" их. Для создания слоя с абсолютным позиционированием (т.е. размещения данного слоя по определенным координатам) исполь- используют дескриптор <Iayer>. Для создания слоя с относи- относительным позиционированием (который появляется там, где размещают дескриптор на HTML-странице) приме- применяется дескриптор <Науег>. Единственная реальная выгода от этих двух деск- дескрипторов Netscape, кроме возможности их стилизации в пределах атрибутов (что является очень незначитель- незначительной выгодой), — это возможность помещения в них вне- внешних HTML-файлов. Такое помещение выполняется с использованием атрибута дескриптора src. Однако, это- этому аргументу можно противопоставить существование дескриптора <iframe> ("i" здесь означает inline — встро- встроенный), который является частью Рекомендаций для HTML 4 и имеет возможность стилизации CSS с теми же самыми функциональными возможностями. К сожа- сожалению, Navigator 4 не поддерживает этот дескриптор. В результате получается расхождение в способах созда- создания слоев. ^ПРИМЕЧАНИЕ . '. Сказанное выше, вероятно, может вызвать головную боль, к тому же возникает вопрос — зачем вообще связываться со слоями? Давайте разберемся. Как упо- упоминалось ранее, реальная проблема состоит в том, что Navigator 4 вышел за рамки стандартов. Однако еще есть надежда: Navigator 5 и 6, браузеры с откры- открытым кодом (Open Source) от Mozilla.org, поддержива- поддерживают CSS и HTML 4, включая стили, необходимые для по- позиционирования, а также дескрипторы типа <iframe> для помещения внешних файлов. Этот раздел посвящен специфике создания слоев. Более подробно они будут рассматриваться позже в гла- главе, а сейчас можно оценить их использование и выго- выгоды, которые обеспечивают слои. В этой главе обсужда- обсуждается не только ряд универсальных действий, но также и действия при использовании методов <div> / <iframe> и <layer> / <ilayer> для создания слоев.
Технологии программирования на динамическом HTML Часть IV Универсальные действия Несмотря на расхождения в способах создания слоев, о котором упоминалось ранее, все движется к более уни- универсальной реализации. В этом разделе рассматривают- рассматриваются некоторые универсальные действия и теоретические аспекты, которые не зависят от метода создания слоев на Web-страницах. Использование таблиц стилей для создания слоев Как было сказано во введении к главе, стандартный способ реализации слоев состоит в том, чтобы управлять ими с помощью таблиц стилей. Этот способ включает все — от позиционирования и моделирования данных, содержащихся в слое, до расположения и визуализации слоев. Свойства CSS перечислены в приведенном ниже списке. • position • left, ight, top и bottom • height и width • z-index • visibility ПРИМЕЧАНИЕ Обратите внимание, что в этой главе не будут рассмат- рассматриваться абсолютно все свойства CSS. Дополнительную информацию о таблицах стилей можно получить в гла- главе 22. . ¦:¦- :;*¦¦ ¦:. . . . . ¦ . ¦ ......... position Свойство position используется для сообщения браузе- браузеру, как и где размещать элементы, к которым применя- применяется это свойство. Существует четыре различных значе- значения этого свойства (см. табл. 23.1). Для лучшего понимания работы этих свойств рас- рассмотрим листинг 23.1. В этом листинге три дескрипто- дескриптора <р> помещены в раздел <body> документа. Каждый из них имеет имя и ID (идентификатор) стиля. В раз- разделе <head> документа каждому 11 > присвоен свой цвет фона (для отображения различий), а также значения left и top. Обратите внимание, что свойство position установ- установлено в absolute. На рис. 23.1 показан результат отобра- отображения в браузере Internet Explorer. ПРИМЕЧАНИЕ В примере преднамеренно не используется дескрип- дескриптор <div> для демонстрации того, что эти типы сти- стилей могут применяться к любому элементу. . Redo О Phy ф ЯШ J :iomft InternetExploter SI HiloSlalwtj • .:j CairMsJOS . : ¦ 1 Links " РИСУНОК 23. '{.Абсолютное позиционирование HTML-элементов.. Листинг 23.1. Абсолютное позиционирование HTML-элементов с помощью свойств CSS. <html> <head> <title>JavaScript Unleashed</title> <style type="text/ess"> #first{ background-color: green; left: 0 ; position: absolute,- top: 0 ; Isecond{ background-color : red; left: 30; position: absolute; top: 3 0; #third{ background-color: blue; left: 60; position: absolute; top: 60; </style> </head> <body> <p name="layerl" id="first"> Layer 1 <p name="layer2" id="second"> Layer 2 <p name="Iayer3" id="third"> Layer 3 ... . : . . :... </body> </html>
Слои Глава 23 Таблица 23.1. Значения свойства position. Значение Описание absolute Это значение сообщает браузеру, что будут определяться абсолютные координаты элемента. При использовании данного значения применяются также свойства top и left. Если они не определены, браузер полагает, что координаты х и у (верхний левый угол окна браузера) равны 0. fixed Это значение аналогично absolute, за исключением того, что не перемещается при прокрутке окна. relative Это значение позволяет сдвигать заданный элемент относительно предыдущего элемента. static Это значение по умолчанию, которое используется в визуализации HTML в современных версиях браузеров. left, right, top и bottom Как видно из предыдущего примера, существуют неко- некоторые CSS-свойства, которые позволяют определять точное расположение элемента. Эти свойства, имеющие числовые значения для координат, нельзя использовать все сразу. Например, элемент не может установить свой- свойство right, если уже установлено свойство left. To же са- самое можно сказать и относительно свойств top и bottom. Если попытаться сделать это, большинство браузеров по умолчанию перейдут к значениям свойства, заданным последним в определении используемых стилей. Например, рассмотрим листинг 23.2, который пред- представляет собой расширение предыдущего листинга за счет добавления четвертого слоя и определения стилей. Применялись различные комбинации свойств right, left, top и bottom для размещения блоков в каждом из четы- четырех углов окна браузера (рис. 23.2). Листинг 23.2. Использование свойств right, left, top и bottom. <html> <head> <title>JavaScript Unleashed</title> <style type="text/css"> <! — #first{ background-color: green; left: 0 ; position: absolute; top: 0 ; 1 ttsecond( background-color: red; position: absolute; right: 0 ; top: 0 ,- #third{ background-color: blue; bottom: 0 ; position: absolute; right: 0 ; «fourth{ background-color: yellow; bottom: 0 ; left: o, position: absolute; </style> </head> <body> <p name="layerl" id="first"> Layer 1 <p name="layer2" id="second"> Layer 2 <p name="layer3" id="third"> Layer 3 <p name: Layer 4 </body> </html> ;:¦?»!¦¦ ?d* '-.View fjv« A*ISS |«JrMEMP\763>OiJ.(l'lrirrJ Layer 4 РИСУНОК 23.2. Определение правой, левой, верхней и нижней позиций HTML-элементов. height и width Следующие два свойства позволяют определять высоту и ширину слоев. Именно поэтому они носят названия height и width. Подобно свойствам, которые позволяют определять расположение слоев, эти два свойства при- принимают числовые значения для определения того, на-
Технологии программирования на дшшмическом HTML Часть IV сколько высоким и широким должен быть слой. Лис- Листинг 23.3 продолжает совершенствовать предыдущий пример, определяя для четырех слоев значения height и width. Результат можно увидеть на рис. 23.3. Листинг 23.3. Использование height и width для определения размера слоев. <html> <head> <title>JavaScript Unleashed</title> <style type="text/css"> ^ i #first{ background-color: green; height:20; left: 0 ; position: absolute; top: 0 width; 40; #second( background-color: red,- height:10; position: absolute; right: 0 ; top: 0 ; width: 30; }¦ #third{ : blue; bottom: 0; height:100; position: absolute; right: 0; width: SO; i #fourth{ background-color: yellow; bottom: 0; height:100; left: 0; position: absolute; width: 200,- </style> </head> <body> <p name="layerl" id="first"> Layer 1 <p name="layer2" id="second"> Layer 2 <p name="Iayer3" id="third"> Layer 3 <p nami Layer 4 ipt Unleashed - Mirai.so» Inlumel Endow Layer 4 I • </body> </html> РИСУНОК 23.3. Определение высоты и ширины слоев. z-index Наступило время разобраться в терминологии слоев. До этого только определялось как выглядят слои — их сти- стилевые характеристики. Теперь слои будут располагать- располагаться так, чтобы получить эффект наложения слоев друг на друга. Для этого используется свойство z-index. Свойство z-index содержит числовое значение, ко- которое определяет расположение слоя относительно окна браузера, которое по умолчанию является нулевым @). Установка для z-index значения 1 о г. что слой размещается поверх окна браузера. Это nopHj в ко- котором слои появляются на странице. При этом, если имеются накладывающиеся друг на друга слои, и у одного из них z-index равен I. то он наложитоя на дру- другой. Помните, что окно браузера имеет z-index, равный О, и располагается под слоем 1. Прежде чем перейти к примеру, посмотрим на лис- листинг 23.4. В нем есть четыре накладывающихся слоя. Они накладываются не потому, что для них установле- установлены значения z-index, а из-за порядка, в котором они по- появляются в документе. Первый слой — самый \ ижний, затем следует второй, третий и четвертый (см. рис. 23.4). Листинг 23.4. Слои с накладывающимися координатами. <html> <head> <title>JavaScript Unleashed</title> <style type="text/css"> #first{ background-color: green; height: 100; left: 0; position: absolute; top: 0 width: 100;
Слои Глава 23 #second{ iund-color: red; height: 100 left: 20; position: absolute; top: 20; width: 100; I #third{ background-color: blue; height: 100 left: 40; position: absolute; top: 40; width: 100; #fourth{ ; yellow; height: 100; left: position: absolute; top: 60; width: </sty.te> </head> <body> <p name=" layer 1" id="first"> Layer 1 name="layer2" id="second"> Layer 2 name="layer3" id="third"> Layer 3 <p name="layer4" Layer 4 </body> </html> Как видно из предыдущего примера, порядок слоев играет важную роль при их отображении. Они действи- действительно уложены друг поверх друга? Нет — это только так кажется. Их можно упорядочить, определяя свой- свойство index. Конечно, если разместить их в том же порядке, они будут выглядеть точно так же, поэтому данное свойство чаще всего используется для изменения порядка, а не для определения стандартного (по умол- умолчанию) порядка при создании Web-страниц. Рассмотрим листинг 23.5. Здесь для первого и тре- слоев устанавливаются значения z-index. По- Поскольку первый слой должен быть верхним, его z- index равно 2, a z-index третьего слоя равно 1. На рис. 23.5 показан результат загрузки кода из этого листинга в браузер. ja JavdSi;ii|il Unleashed - Mniosoll Inteinol Eiploiei jit Ц- Vo Fortes Is* РИСУНОК 23.4. Слои, накладывающиеся из-за порядка следования в документе. Листинг 23.5. Изменения значения z-index слоев. <html> <head> < ti tle> JavaScrip t Unleashed*:/ ti tle> <style type="text/css"> <>— #first{ background-color: green; height: 100; left: 0; position: absolute; top: 0 ; width: 100; z-index: 2; #second{ background-color: red; height: 100; left: 20; position: absolute; top: 20; width: 100; I #third{ background-color: blue ; height: 100; left: 40; position: absolute; top: 40 ; width: 100; z-index: 1; ttfourth{ : yellow; height: left: position: absolute; top: width: 100;
Технологии программирования на динамическом HTML Часть IV </style> </head> <body> <р name="layerl" id="first"> Layer 1 <p name="layer2" id="s Layer 2 <p name="layer3" id="third"> Layer 3 <p name="layer4" id="fourth"> Layer 4 </body> </html> РИСУНОК 23.5. Изменение наложения слоев из предыдущего примера.. visibility Последнее из рассматриваемых свойств — visibility, ко- которое принимает четыре разных значения, перечислен- перечисленные в табл. 23.2. Как и следовало ожидать, это свойство отвечает за сокрытие и отображение слоев. Для демонстрации использования этого свойства возьмем код предыдущего примера и добавим к нему две строки. Помните два слоя, для которых устанавливались значения z-index? При этом они стали самыми верхни- верхними на странице. В определении стиля установим их зна- значения visibility в hidden. Листинг 23.6 содержит данный код, а рис. 23.6 демонстрирует, что эти два слоя теперь не видны. Листинг 23.6. Использование свойства visibility для сокрытия элементов. <html> <head> <title>JavaScript Unleashed</title> <style type="text/css"> <• #first{ background-color: green; height: 100; left: 0; position: absolute; top: 0 ; width: 100; z-index: 2,- visibility: hidden; #second{ background-color: red; height: 100; left: 20,- position: absolute; top: 20; width: 100,- #third{ background- color: blue ; height: 100; left: 40; position: absolute,- top: 40; width: z-index: 1 ; visibility: hidden; j #fourth{ background-color: yellow; height: 100; left: 60; position: absolute; top: 60; width: 100; </style> </head> <body> <p name="layerl" id="first"> Layer 1 <p name="layer2" id=": Layer 2 <p name="layer3" id="third"> Layer 3 <p name="layer4" id="fourth"> Layer 4 </body> </html> Управление накладывающимися слоями Рассмотренные CSS-свойства позволяют создавать интересные визуальные эффекты. Например, предполо- предположим, что требуется отобразить на Web-странице неко- некоторую диаграмму с отчетными данными. Цель заклю- заключается в отображении одной диаграммы в каждый момент времени и предоставлении пользователю воз- возможностей просмотра других диаграмм.
Слои Глава 23 Таблица 23.2. Значения свойства visibility. Значение Описание collapse Это значение аналогично collapse (см. ниже) всегда, кроме случаев использования в таблицах, hidden Это значение скрывает элемент. inherit Это значение по умолчанию, определенное в браузере; принимает то же самое значение, что и его родительский элемент. visible Это значение делает элемент видимым. РИСУНОК 23.6. Сокрытие слоев. Возможно, те, кто работает в среде Windows, вспом- вспомнят, что для достижения подобных целей можно ис- использовать окно со вкладками (по одной вкладке для каждой диаграммы). Точно такой же эффект на Web- странице можно создать при помощи слоев. Однако, при создании слоев важно помнить, что ими необходимо эффективно управлять. Воспроизведе- Воспроизведение вкладок, списков либо элементов меню, применяе- применяемых в каждодневных прикладных программах, — весьма непростое дело. Необходимо запоминать предыдущее состояние элемента или даже набора элементов, чтобы, когда один из них изменяется, все остальные также бы изменялись. Например, при нажатии вне области меню оно должно исчезать, т.е. требуется перехватывать со- события нажатия на кнопку мыши. В данной главе эти темы не обсуждаются; они подробно рассматриваются в главе 24. Создание мультипликационных эффектов Другой интригующей возможностью слоев является создание мультипликации. Поскольку JavaScript позво- позволяет позиционировать слои, можно создавать рекурсив- рекурсивные юдпрограммы, в которых слои будут как бы сколь- скользить или прыгать по документу. Именно комбинация HTML и JavaScript позволяет создавать динамический HTML (DHTML). Используя слои, JavaScript и таблицы стилей, мож- можно создавать (с помощью HTML) элементы на страни- странице, улучшать их внешний вид (через CSS), а также уп- управлять этими элементами (с помощью JavaScript). С такими модификациями, как улучшенная поддержка DOM-модели и XML (extensible Markup Language - расширяемый язык разметки) в браузерах, возможнос- возможности становятся поистине безграничными. <div> и <iframe> Теперь, когда известны основы создания слоев, пришло время познакомиться с их спецификой. Даже при том, что Netscape-метод использования <1ауег> и <ilayer> для реализации слоев был отвергнут, все же стоит о нем поговорить позже в главе. А сейчас будет обсуждаться более универсальный метод реализации слоев — через дескрипторы <iframe> и <div>. Определение блоков данных Первый шаг в создании слоев должен заключаться в определении блока данных, предназначенных для дан- данного слоя. В случае браузера его окно должно считать- считаться первым слоем. При нажатии на меню оно отобража- отображается поверх окна — т.е. это второй слой поверх первого слоя (окна браузера). При нажатии на выпадающем под- подменю появляется еще один слой (который может при- принадлежать или нет тому же уровню, что и первый). Методом определения этих блоков данных являет- является применение дескриптора <div>. Этот дескриптор со- создает определенную иерархическую структуру блоков в документе. В терминах выполнения этот дескриптор подобен дескриптору <р>, за исключением того, что <р> предназначен как для определения начала нового абзаца, так и для следующих за ним данных как состав- составляющих данный абзац. Дескриптор <div>, напротив, только определяет данные, но не сообщает браузеру, как их отображать. Перед рассмотрением метода перемещения слоев или блоков <div> изучим атрибуты этого дескриптора и их значения. Все эти атрибуты сведены в табл. 23.3.
Технологии программирования на динамическом HTML Часть IV 23.3. Атрибуты дескриптора <div>. Значение Описание align Используется для выравнивания данных, содержащихся внутри дескриптора <div>, может принимать значения left (по левому краю), right (по правому краю), center (по центру) и usiily (по ширине). Этот атрибут был отвергнут в пользу применения CSS. class Разделенный запятыми список классов стилей, которые делают дескриптор экземпляром этих классов. Определяет направление любого текста, содержащегося в дескрипторе. Значение Iti означает слева направо, а значение > t — справа налево. id Часто используется в таблицах стилей для определения типа стиля, который должен применяться к данным внутри дескриптора. Идентифицирует язык для текста внутри дескриптора. mame Используется для именования экземпляра блока. Может применятся в JavaScript для управления слоями, style Позволяет определять стиль внутри дескриптора, а не в таблице стилей. title Обеспечивает более информативный заголовок для дескриптора по сравнению с дескриптором <title>, который применяется для всего документа. Определение блока данных Использование дескриптора <div> — совершенно про- простое дело. Все, что необходимо — это пространство вок- вокруг элементов, которые необходимо определить как блок данных. Листинг 23.7 демонстрирует, как это сделать. Как видно из листинга, в этом примере содержится два блока <div>. Внутри первого находятся две горизонталь- горизонтальных линии (дескрипторы <hr>) и текст DIV 1. Во вто- второй блок включен заголовок третьего уровня (дескрип- (дескриптор <h3>) и абзац (дескриптор <р>). В него также входит некоторый текст перед и после каждого блока <div>TaK, чтобы было видно, где они начинаются и за- заканчиваются. Результат выполнения этого листинга в браузере Opera показан на рис. 23.7. Листинг 23.7. Использование дескриптора <div>. <html> <head> <title>JavaScript Unleashed*:/title> </head> <body> Before the first block. <div name="layerl"> <hr> DIV 1 <hr> After the first block. <br> Before the second block. <div name="layer2"> <h3> DIV 2 </h3> <P> I am inside the second DIV block. After </body> </html> the second block. Before the first blot DfVI After the first block. Before the DIV 2 I am inside the sect After the second bbclc РИСУНОК 23.7. Определение блоков данных в документах. Позиционирование блоков <div> Теперь рассмотрим применение позиционирования к блокам данных. Для этого необходимо присвоить свой- свойства id дескрипторов и определить свойства ст :й для каждого из них. Определим сначала расположение, раз- размер и цвета фона, поскольку это очевидно. Все элемен- элементы рассматривались ранее в главе. Листинг 23.8 содер- содержит необходимый код, а рис. 23.8 показывает, как будет выглядеть отображение кода в браузере. Как видно из рисунка, позиционирование было установлено так, что- чтобы второй блок помещался слева от первого, а первый накладывался на часть текста. Листинг 23.8. Применение таблиц стилей и позиционирования к блокам <div>. <html> <head> <title>JavaScript Unleashed</title> <style type="text/css">
ttflrst{ background-color: green; height: 100; Left: 275; position; absolute ,¦ top: 40; width: 100; I ttsecondf background-color: red; height: loo; left: 100,- position: absolute; top: 55; width: 100; <7style> </head> <body> Before the first block. <div name="layerl" id="first"> <hr> DIV 1 <hr> After the first block. <br> Before the second block. <div name="layer id="second"> <h3> DIV 2 </h3> I am inside the second DIV block. After the second block. </body> </htirl> /правление с помощью JavaScript Сейчас, после П 'о как проделаны первые шаги в созда- создании слоев и определении их характеристик, можно до- добавлять возможности JavaScript. В этом разделе иссле- исследуются JavaScript-способы динамических замен, отображений и перемещений слоев. ПРИМЕЧАНИЕ Главная цель этой главы заключается в представлении слоев. Если уже есть понимание методики создания слоев и обращения к ним через JavaScript, можно сразу перейти к главе 24, где более подробно рас- рассматривается практическое применение этих двух тех- технологий. 1Я вещь, которую следует понять во время изу- изучения JavaScript для манипуляции слоями, — это синтак- синтаксис. Из-за различий между Internet Explorer и Navigator, к слоям обращаются различными методами. В браузерах Navigator к слоям обращаются через мас- массив layers. В дескрипторе <div> имеется атрибут name, с помощью которого можно определить имя слоя. Сле- Слои Глава 23 дующая строка кода используется для обращения к пер- первому слою: document.layers ['layer'] Beforethe first block After the first block. Before the sccondblock. Afterthe second РИСУНОК 23.8. Позиционирование блоков данных. В Internet Explorer, в отличие от Navigator, к слоям обращаются через массив all. Значение, определяющее слой, к которому обращаются, содержится не в атрибуте name дескриптора <div>, а в атрибуте id. В предыдущем примере для обращения к первому слою применяется показанная ниже строка кода. Обратите внимание, что здесь применяется first — значение атрибута id: document.all ['first'] ПРИМЕЧАНИЕ Это не единственный способ обращения к слоям из кода JavaScript. Однако, это лучший способ для уче- учета особенностей Navigator и Internet Explorer, посколь- поскольку он требует минимального объема кодирования. В среде Navigator можно обращаться к свойствам слоя сразу же после объявления document.layers[7aj>e/'j'Vame1]. Для случая Internet Explorer, однако, к ним обращаются через массив style, что означает применение синтаксиса примерно такого вида — document.all {'layerName'].style. Рассмотрим пример. Предположим, что isNav означает, что использует- используется браузер Navigator, a isIE — что используется Internet Explorer. Следующий условный оператор if из листинга 23.8 скрывает первый слой. if(isIE){ document.all['first'].style.visibility — "hidden"; }else if(isNav){ document.layers['layerl'].visibility = "hidden";
Технологии программирования на динамическом HTML Часть IV При создании сценариев, предназначенных для ра- работы в обоих браузерах, в дескрипторе <div> исполь- используют одно и то же значение как для name, так и для id. Кроме того, потребуется хранить в переменной ссылку на массив, к которому обращаются. Можно сделать то же самое для требований стиля в Internet Explorer. Сле- Следующий псевдокод решит упомянутые проблемы. var layer = new String (); var style = new String () ; if(isIE){ .layer = ".all"; style = "style"; }else if<isNav){ layer = " . layers" ; style = " Теперь имеется достаточно информации для форми- формирования фун! работающей во всех браузерах, ко- которая будет работать со слоями. Однако, требуется пред- предпринять последний шаг — включить использование метода eval(). Этот метод будет обрабатывать строку как JavaScript-вызов. Можно "построить" требуемый вызов для доступа и изменения свойств слоя, например, свой- свойства visibility. В листинге 23.9 все рассуждения собраны вместе. Как видно из листинга, с помощью некоторых CSS-P- свойств был создан одиночный слой, который появля- появляется под двумя кнопками в окне браузера. После загруз- загрузки страницы вызывается функция checkBrowser(), которая определяет, что это за браузер — Internet Explorer или Navigator. Там также хранится необходимый мас- массив для доступа к слоям — layer. Каждая из кнопок выполняет вызов функции changeState(), передавая значение и ссылку на слой. Значение сообщает функции, надо ли отображать пере- переданный слой. Затем эта функция считывает переданные ей параметры и при помощи метода eval() изменяет со- состояние слоя. На рис. 23.9 показан вид страницы перед нажатием кнопки "Hide". Пример одинаково хорошо работает как в Internet Explorer, так и в Navigator. Листинг 23.9. Доступ к слоям через JavaScript. <html> <head> <t it le> JavaScript Unleashed*:/title> <style type="text/css"> <! — #layerl{ background-color: green; height: 100; left: 10; position: absolute; top: 50; width: 100, I —> </style> <script type="text/javascript" language="JavaScriptl.2"> <! — // Глобальные переменные для браузера var layer = new Stri ig () ; var style = new String-() ; // С каким браузером инеем дело: // Explorer, Navigator, или другой? // Установка соответствующих значений // переменных для браузера. function checkBrowser(){ if(navigator.userAgent.indexOf("MS1E") '=-l){ layer = ".all"; .style = ".style"; )else if(navigator.userAgent. ;"Nav") != -1) { layer = ".layers"; style = ' / / Изменение состояния . function changeState (layerRef, stati eval ("document" + layer + "['" + layerRef + " ' ] " + style + " .visibility = ' " + state + > } II—> </script> </head> <body onload="checkBrowser () "> <div name=" layerl" id="layerl"> DIV 1 </div> <form name="forml"> <input type="button" value="Hide" onclick="changeState( ' layerl1 , 'hidden')"> <input type="button" value="Show" onclick="changeState('layerl' ,'visible') "> <form> </body> </html> РИСУНОК 23.9. Содержимое страницы перед нажатием кнопки.
Вставка внешних файлов Используя дескриптор <iframe>, можно выполнять встав- вставку внешних файлов. Это дает возможность лучше управ- управлять содержимым и обеспечивает механизм включения содержимого из различных расположений. ПРЕДУПРЕЖДЕНИЕ' Даже при том, что дескриптор <iframe> является час- частью Рекомендаций для HTML 4, в браузерах Navigator он в настоящее время не поддерживается. Однако, под- поддержка этого дескриптора будет добавлена в Navigator ,5 (называемый также Mozilla), браузер с открытым ис- исходным кодом от Mozilla.org. Пока же для эмуляции функциональных возможностей этого дескриптора мож- можно воспользоваться дескриптором <ilayer> браузера Navigator 4.x. Слои Глава 23 Хороший пример применения этого дескриптора - создание на сайте раздела свежих новостей. Предполо- Предположим, что требуется обновлять новости ежедневно, од- однако не хочется ежедневно обновлять каждую страни- страницу, на которой они появляются. Используя дескриптор <iframe>, можно ссылаться на одну страницу, содержа- содержащую сегодняшние новости. При этом изменения будут производиться только в одном месте и появятся на всех соответствующих страницах. Сказанное стоит проиллюстрировать примером. Как видно из листинга 23.10, вызывается внешняя страни- страница с именем news.html (которая находится в листинге 23.11). Дескриптор ссылается на эту страницу с помо- помощью src и других атрибутов. На рис. 23.10 для <iframe> задана граница, чтобы слой был более четко виден. В табл. 23.4 перечислены атрибуты дескриптора <iframe>. Листинг 23.10. Использование дескриптора <iframe> для загрузки внешних файлов. <html> <head> <title>JavaScript Unleashed</title> <style type="text/css"> ^ i —— #layerl{ height: 100; left: 10; position: absolute; top: 50; width: 100; i > > </style> ocript type="text/javascript" language="JavaScriptl.2"> <? — У/ Глобальные переменные для представления типа браузера var isIE = new Boolean (false) ; var isNav = new Boolean (false) ; var unsupported = new Boolean(false) ; var layer = new String () ; var style = new String () ; // Определение типа браузера: // Explorer, Navigator, или другой. Установка переменной // слоя вэависимоста! от требуемой формы доступа, function checkBrowser()( if(navigator.userAgent.indexOf("MSIE") != -1) { isIE = true; layer = ".all"; style = ".style"; }else if(navigator.userAgent.indexOf("Nav") != -1){ isNav = true; layer = ".layers"; style = ""; }else< unsupported = true; // Изменение состояния. function changeState (layerRef, state) { eval ("document" + layer + " ['" + layerRef Estate + ); styie .visibility =
Технологии программирования на динамическом HTML Часть IV II—> </script> </head> <body onload="checkBrowser()"> <ifraine name="layerl" id="layerl" src="news .html" frameborder="l" noresize scrolling="no"X/iframe> <form name="forml"> <input type="button" value="Hide" onclick="changeState('layerl','hidden')"> <input type="button" value="Show" onclick="changeState('layerl','visible')"> <form> </body> </html> Таблица 23.4. Атрибуты дескриптора <iframe>. Значение Описание align Используется для выравнивания данных внутри дескриптора <ifra ie>. Допустимыми значениями являк left, right, top, middle и bottom. От него отказались в пользу CSS. class Разделенный запятыми список классов стиля, который определяет дескриптор как экземпляр указанных классов. Может принимать значения 0 или 1 для указания, существует ли граница вокруг фрейма, height Определяет высоту <iframe>. id Часто используется таблицами стилей для определения стиля, который должен применяться к данным в дескрипторе. Jongdesc Ссылается на более полное описание содержимого дескриптора. marginheight Количество пикселов между содержимым фрейма и верхней и нижней границами. Количество пикселов между содержимым фрейма и правой и левой границами. name Используется для именования блока. Применяется в JavaScript для управления слоями, noresize Если присутствует, изменение размеров фрейма со стороны пользователя запрещав' scrolling Принимает значения auto, yes или по для определения, должны ли отображаться полосы npoi src Определяет URL, в котором хранится содержимое <iframe>. style Позволяет указывать определение стиля внутри дескриптора вместо внешнего указания в таблице стилей. title Позволяет обеспечить более информативный заголовок для <iframe> по сравнению с дескриптором <title>, который относится ко всему документу. width Определяет ширину <iframe>. Листинг 23.11. Содержимое внешнего файла. <html> <head> <title>JavaScript Unleashed*:/title> </head> <body bgcolor="red"> <P> rhis is the news pag< </body> </html> РИСУНОК 23.10. Результат загрузки листинга 23.10'в Internet Explorer. Из сказанного выше становится понятно, что воз- возможности управления слоями с помощью 'avaSc весьма обширны. Однако, как упоминалось ранее, су- существует некоторое несоответствие между основными браузерами. Internet Explorer более точно реализует стан- стандарты HTML 4 и ECMAScript, a Navigator вводит ряд новых дескрипторов для обра( 31 слоев. В следующей
версии они будут поддерживать Рекомендации для HTML 4, пока же необходимо ограничиться дескрип- дескрипторами <1ауег> и <ilayer>. В последнем разделе главы обсуждаются эти деск- дескрипторы и способы их использования. Хотя здесь уже были представлены базовые Принципы, однако, деталь- детальное рассмотрение формирования DHTML с помощью этих дескрипторов приводиться не будет. <1ауег> и <ilayer> В Navigator слои определяются с помощью дескрипто- дескрипторов <1ауег> и <ilayer>. Элементы <1ауег> позволяют точно располагать слой на странице, а элементы <ilayer> появляются везде, где их размещает текущий документ. Свойства дескрипторов <1ауег> и <ilayer> собраны в табл. 23.5. Как видно из таблицы, эти дескрипторы содержат большинство тех же самых атрибутов, что и другие деск- дескрипторы, применяемые при создании DHTML. Однако, в отличие от других элементов в браузерах Navigator слой имеет свой собственный JavaScript-объект: объект Layer. ПРИМЕЧАНИЕ '" ". ¦*¦"' Этот объект был описан в главе 9, поэтому его мето- методы и свойства здесь подробно рассматриваться не будут. Пример страницы со вкладками Для лучшего понимания функциональности дескрипто- дескрипторов <1ауег> и <ilayer>, стоит обратиться к нескольким примерам. Возьмем четыре изображения в формате GIF Слои1 Глава 23 и с их помощью отобразим диаграммы на странице со вкладками (см. рис. 23.11). Каждое из этих изображе- изображений присваивается отдельному слою HTML-документа. Элементам <1ауег> устанавливаются одинаковые пара- параметры left и top для выравнивания их друг относитель- относительно друга. <layer name="tab3" left=5 top=55> <img src="./1994tab.gif"> </layer> <layer name="tab2" left=5 tqp=55> <img src="./1995tab.gif"> </layer> <layer name="tabl" left=5 top=55> <img src="./1996tab.gif"> </layer> <layer name="tabO" left=5 top=55> <img src="./1997tab.gif"> </layer> ПРИМЕЧАНИЕ В слоях используется концепция "последний должен быть первым" (или "самым верхним"). Обратите внимание, что в приведенном выше коде вкладка для 1997 г. в HTML-файле была определена последней. Определенный в последнюю очередь элемент слоя считается самым верхним и будет отображаться поверх всех остальных. С целью обеспечения лучшего взаимодействия с пользователем был определен еще один слой, содержа- содержащий форму со списком выбора. Пользователь теперь может выбирать для просмотра элемент из списка. Мож- Можно определить обработчик событий onChange, который бы вызывал функцию showTab() и передавал ей в каче- качестве параметра выбранную опцию. Ниже показан соот- соответствующий код: Таблица 23.5. Свойства дескрипторов <1ауег> и <Мауег>. Свойство Описание above Положение объекта Layer повышается в порядке z-order всех слоев документа (null, если слой — самый верхний). backg'ound URL изображения, используемого в качестве фона для слоя. below Положение объекта Layer понижается в порядке z-order всех слоев документа (null, если слой — самый нижний). bgcolor Цвет фона для слоя. clip Определяет прямоугольник отсечения, который является видимой областью слоя. Все, что находится вне этого прямоугольника, отображаться не будет. heigh1: Высота слоя в пикселах. left Координата в пикселах слоя по оси X относительно начала координат его родительского слоя. name Имя слоя. src URL для источника, содержащего данный слой. top Координата в пикселах слоя по оси Y относительно начала координат его родительского слоя. visibility Определяет атрибуты видимости слоя, show отображает слой, hide скрывает слой, a inherit заставляет слой наследоватьусловия видимости от его родительскогослоя. width Ширина слоя в пикселах. z-index z-порядок слоя относительно элементов того же уровня и родительского элемента.
Технологии программирования на динамическом HTML Часть IV <layer name="seleot" left=00" top=5 width=50"> <center> document.layers t"tab"+idx].visibility = 'inherit'; Select the year to viewr <form name="selectForm"> <select name="pickYear" size="l" onchange="showTab(this. selectedlndex),; return false ;"> <option selected>1997</option> <option>1996</option> <option>1995</option> <option>1994</option> </seleot> </form> </center> </layer> РИСУНОК 23.11. Изображение в формате GIFna странице со вставками. ПРИМЙАНИЕ Оптимальнее всего было бы иметь карту изображения, определенную для границ вкладок. Связывая с этими областями обработчик событий onClick, можно смо- смоделировать стандартный элемент управления типа стра- страницы со вкладками. Теперь создадим функцию showTabQ для отобра- отображения выбранной диаграммы. Для этого сначала не- необходимо скрыть все слои, а затем сделать выбранный слой видимым. Следующий код использует массив document.layers для прохода через каждый слой в доку- документе и скрывает все слои, кроме Select. Затем выбран- выбранной вкладке присваивается значение inherit, что делает ее видимой. function showTab (idx) { for (var i =! 1; i < document, layers, length; ){ if(document.layers[i].name != 'Select')) document.layers[i].visibility = 'hide' При просмотре и тестировании кода из списка вы- выбора можно выбрать год для отображения соответству- соответствующей диаграммы. На рис. 23.12 показаны результаты выбора 1996 г. Листинг 23.12 содержит полный исходный код для этого примера. Листинг 23.12. Использование слоев для моделирования Web-страницы со вкладками.. <html> <head> <title>JavaScript Onleashed</title> <script type="text/javascript" language="JavaScriptl.2"> function showTab(idx) { for (var i = 1; i < document.layers.length; i++){ if(document.layers[i].name != 'Select'){ document.layers[i].visibility = 'hide'; :i ч document.layers["tab"+idx] .visibility = 1 inherit' ; I II—> </script> </head> <body bgcolor="Silver"> <h4> AMAZING SCUBA GEAR Sales History /h4> < layer name="tab3" left=5 top=55> <img src=" . /1994tab.gif"> </layer> <layer name="tab2" left=5 top=55> <img src=" . /1995tab.gif "> </layer> <layer name="tabl" left=5 top=55> <img src="./1996tab.gif"> </layer> <layer name="tabO" left=5 top=55> <img src=" ./1997tab.gif"> </layer> <layer name="select" left=00" top="S5" width=50"> <center> Select the year to view: <?orm name="selectForm"> <select name="pick Year" size="l" onchange="showTab(this.selectedlndex); return false;">
<option selected>1997</option> <option>199 6</option> <option>1995</option> <option>l994</option> </select> </form> </center> </layer> </body> </html> -;. i':':"»?' „¦.'¦"..'¦—-' ;,„. „, \ -, 'i* «*¦ 'J &•!•« '""' f1»-*1 * :.-.-¦¦¦ 'm-{: i "¦¦иг! *]. РИСУНОК 23.12. Слом с диаграммой для 1996г. сделан видимым. Пример со сталкивающимися шариками Во втором примере будет создаваться мультипликаци- мультипликационный эффект. Для получения эффекта сталкивающе- сталкивающегося шарика воспользуемся тремя разными изображени- изображениями в формате GIF, которые будут содержать картинки зеленого, красного и разноцветного шарика. Поместим каждый из шариков в отдельный элемент <1ауег>: <layer name="greenball" width=3" height=3" left=" top="l"> <img src="./grnball.gif"> </layer> <layer name="redball" width=3" height=3" le?t=5" top=35"> <img src="./redball.gif"> </layer> <layer name="colorball" width=3" height=3" left=55" top=15"> <irng src=" . /clrball .gif </layer> Параметры width и height элементов <Iayer> имеют те же самые размерности, что и GIF-изображения. Па- Параметры left и top — случайные числа в пределах кар- картинки, которые произвольно задаются как 400 пикселов по горизонтали и 200 пикселов по вертикали. Они бу- будут служить в качестве координат начального положе- положения шариков. Слои Глава 23 После элемента <script> внутри раздела <head> до- документа можно определить ряд глобальных перемен- переменных, используемых в подпрограммах мультипликации. Для каждого из шариков применяется метод offset() объекта Layer, который позволяет изменять позицию слоя с использованием диапазона изменений значений х и у, или delta. Запишем для каждого шарика пару зна- значений диапазона изменений х и у: var var var var var var grnX = grnY = redX = redY = colorX colqrY 2; 2. 2; -2 = = 5; 2; 4 Таким образом, при использовании в offset() эти переменные требуют, чтобы зеленый шарик сместился влево на 2 пиксела и вниз на 2.5 пиксела, красный ша- шарик — влево на 2 и вниз на 2 пиксела, а разноцветный шарик — влево на 2 и вниз на 3 пиксела. Определим также в сценарии, что новое свойство объекта Window с именем flickerFree будет установлено в true. Это свойство помогает обеспечить эффекты бо- более плавной мультипликации: window.flickerFree = true; Перед работой с элементами <1ауег> в данном JavaScript-коде потребуется присвоить переменным ссылки на каждый слой. В разделе <body> документа добавим новый элемент <script> и поместим в него сле- следующий код: <script type="text/javascript" language="JavaScriptl.2"> <¦ i Var green = document.layers["greenball"]; var red = document.layers['redball']; var color = document.layers['colorball1]; II--> </script> Используя массив document.layers, можно обращать- обращаться к каждому из слоев по имени и присваивать их пе- переменным, представляющим слои в сценарии. ПРИМЕЧАНИЕ В отличие от определенных ранее числовых перемен- переменных, нельзя размещать этот код установки значения объекта Layer в разделе <head> сценария, посколь- поскольку он ссылается на элементы, определенные позже, В разделе <body>. Следовательно, ЭТОТ КОД присва- присваивания должен обрабатываться после определения элементов <1ауег>. Определение функций мультипликации Следующий шаг связан с созданием сценария, факти- фактически выполняющего мультипликацию. Изначальная
Технологии программирования на динамическом HTML Часть IV цель довольно проста: отобразить каждый шарик в дви- движении, опираясь на ранее определенное значение offset(). Однако, в действительности кроме определения этих основных функциональных возможностей потре- потребуется проделать очень многое. Потребуется отслеживать координаты х и у каждо- каждого шарика перед каждым обращением к offsetQ. Если этого не делать, шарики очень быстро покинут грани- границы изображения 400x200 и границы самого HTML-до- HTML-документа. Поэтому, если свойство left объекта Layer на- находится между 0 и 400, а свойство top — между 0 и 200, то метод offset() вызывается. Однако если слой не со- соответствует этим условиям, процесс выполняется в об- обратном направлении, имитируя рикошет шарика. Посмотрим, как это реализуется в сценарии. Будут использоваться две функции: ¦• StartTheBallRoIlingO — основная рекурсивная фун- функция, ответственная за вызов каждого шарика для целей мультипликации. Она также выполняет необ- необходимые корректировки значений смещения, когда шарик покидает границы изображения. • moveBall() — отвечает за перемещение шарика в рам- рамках изображения. Она анализирует свойства top и left шарика и вызывает действие offsetO, если они удов- удовлетворяют условиям. Если условия не выполняют- выполняются, эта функция обращается к StartTheBallRoIlingO, которая корректирует смещение. Поскольку moveBall() вызывает StartTheBallRoIlingO, возможно, имеет смысл сначала рассмотреть moveBall(), а затем вернуться к StartTheBallRoIlingO. Функция moveBallO получает три аргумента: ссылка на объект шарика, и его значения смещения по х и у. Как упоми- упоминалось ранее, она проверяет свойства left и top шарика и реализует один из следующих пунктов: Выполняет offsetO и возвращает значение 'ok" в StartTheBallRoIlingO. Возвращает в вызвавшую функцию значение "topBoundary1, обозначая, что свойство top не удов- удовлетворяет условию. Возвращает в вызвавшую функцию значение 'IeftBoundary1, обозначая, что свойство left не удов- удовлетворяет условию. Код приобретет следующий вид: function moveBall (ball, offsetX, offsetY){ if ((ball, left < 400) &S (ball.left > 0)) { if {(ball, top < 200) SS (ball.top > 0)) ( ball.offset(offsetX, offsetY); return 'ok' ; }else{ return 'topBoundary'; }else{ return 'leftBoundary' Теперь рассмотрим функцию, которая обращается к moveBallO. Для каждого из трех шариков StartTheBallRoIlingO вызывает moveBallO и затем анализирует результаты выполнения. Для зеленого шарика код выглядит так: if (moveBall(green, grnX, 1topBoundary'){ grnY = 0-grnY; green.offset(grnX, }else{ if(moveBall(green, 'IeftBoundary') { grnX = 0-grnX; green.offset(grnX, grnY) == grnY); grnX, grnY) = grnY) !¦ Если moveBallO завершилась успешно и вернула зна- значение 'ok', сценарий переходит на следующий шаг. Од- Однако, если возвращается 'topBoundary" (или "IeftBoundary'), это означает, что необходимо подкорректировать значе- значение смещения по у (либо по х). Для этого неудовлетво- неудовлетворительное значение смещения заменяется на новое, де- делая его равным нулю минус его текущее значение. Затем выполняется действие offsetO, которое смещает шарик в обратном направлении. Код совершенно аналогичен для красного и разноцветного шариков: if(moveBall(red, redx, redY) == 'topBoundary'){ redY = 0-redY; red.offset(redX, redY); )else{ if (moveBall (red, redX, redY) == 1IeftBoundary'){ redX = 0-redX; red.offset(redX, redY); ) 5 if(moveBall(color, colorX, colorY) == 1topBoundary')( colorY = 0-colorY; color.offset( colorX, colorY ) ; )else I if(moveBall( color, colorX, colorY) == 'IeftBoundary'){ colorX = 0-colorX; color.offset! colorX, colorY); I } Наконец, вызывается setTimeout(), чтобы сделать этот полный процесс рекурсивным: setTimeout("StartTheBallRoIlingO ", 2) ; Заключительный шаг связан с фактическим запус- запуском шарика за счет установки StartTheBallRoIlingO в ка- качестве обработчика для события on Load окна: <body onload="startTheBallRolling(>">
После определения функций мультипликации код следует протестировать. На рис. 23.13 и 23.14 показан результирующий мультипликационный эффект. Листинг 23.13 содержит полный исходный код де- демонстрационной версии BallsGoneWild. РИСУНОК 23.13. Шарики в движении. Листинг 23.13. Мультипликационные эффекты на Web-странице. <html> <head> <title>JavaScript Unleashed</title> <script type="text/javascript" language="JavaScriptl.2"> // Глобальные переменные var grnX = 2 ; var grnY = 2.5; var redX = 2; var redY = -2; var colorX = 2 ,- var colorY = 3 ; // Эффекты плавной анимации window. flickerFree = true; function moveBall (ball, offsetX, [(ball.left < 400) && (ball.left > 0 if ((ball.top < 200) ss (ball.top > 0) ) { ball.offset(offsetx, offsetY) ; return ' ok * )else{ return ' topBound )else{ return ' leftBoundary ' ; 1 function startTheBai: i ( if grnX, grnY) 'topBoundary1 ) { Слои Глава 23 grnY = 0 - grnY; green.offset(grnX, grnY); )else( эп, grnX, grnY) 1leftBoundary'){ grnX = 0 - grnX; green.offset(grnX, grnY); f (moveBall (red, redX, redY) 'topBoundary')( redY = 0 - redY; red.offset(redX, redY) ; )else{ if (moveBall (red, redX, redY) == 1 leftBoundary' ) { redX = 0 - redX; red.offsetfredX, redY) ; i if (moveBall (color, colorX, colorY) 'topBoundary') ( colorY = 0 - colorY; colorX, colorY ) )else{ if (moveBall( color, colorX, colorY) 'leftBoundary ' ) { colorX = 0 - colorX; iet ( colorX, colorY) ; i setTimeout ("startTheBallRollingO" , 2) ; </script> </head> <body onload="startTheBallRolling()"> <layer name="gre height=3" left=" top="l"> <img src="./grnball.gif"> </layer> <layer name="redball" width=3" height=3" left=5" top=35"> <img src="./redball.gif"> </layer> <layer name="colorball" width=3" height=3" left=55" top=15"> <ixng src=" ./clrball.gif "> </layer> <script type="text/javascript" language="JavaScriptl .2"> <! — Var green = document.layers["greenball"] ; var red = document.layers['redball']; var color = docume //—> </script> </body> </html>
Технологии программирования на динамическом HTML Резюме Слои представляют собой одно из наиболее значитель- значительных достижений в HTML за последние несколько лет. Они позволяют выйти за рамки последовательного тек- текстового процессора и погрузиться в мир HTML, графи- графики и дизайна. JavaScript эффективно работает со слоя- слоями, обеспечивая разработчикам полный контроль их поведения. Результаты получаются великолепными. РИСУНОК 23.14. Шарикивдействии.
Меню и панели инструментов DHTML В ЭТОЙ ГЛАВЕ Начальные предположения Проектирование меню Создание инструментальных панелей Знание языка JavaScript и способов его практичес- практического применения — две совершенно разные вещи. Мно- Многие способны выучить язык программирования, понять его синтаксис и семантику. Однако очень немногие до- достигают действительного мастерства в применении сво- своих знаний для решения практических задач, т.е. при со- создании реальных приложений. Динамический HTML (DHTML) впервые появился в четвертых версиях браузеров Internet Explorer и Netscape Navigator. Оба эти браузера поддерживали JavaScript, слои и таблицы стилей, необходимые для проектирова- проектирования страниц, у которых полный набор динамических свойств постоянно находился на исходной Web-страни- Web-странице. Именно это способствовало возникновению DHTML, и с тех пор такие технологии применяются на многих сайтах, придавая им яркость и усиливая функ- циональныевозможности. В этой главе рассматриваются два примера DHTML- приложений. Первый пример — меню, а второй — ин- инструментальная панель. Как и в повседневной практи- практике, придется решить, какие браузеры поддерживать и выяснить все отличительные особенности работы бра- браузеров в рамках реализации примеров. Начальные предположения Перед началом создания проекта DHTML возникает несколько вопросов, которые задает себе каждый разра- разработчик. Некоторые из них обсуждались в главе 23, тем не менее, имеет смысл еще раз напомнить о них: Какие браузеры требуется поддерживать? Помните, что в настоящее время только Navigator 4+ и Internet Explorer 4+ обладают всеми функциональными воз- возможностями, необходимыми для создания DHTML- приложений. Требуется ли адаптировать код под не поддержива- поддерживающие браузеры? Насколь изящно требуется обходить возникающие проблемы в неподдерживающих браузерах? Вопросы подобного рода уже обсуждались ранее, поэтому детализация здесь будет излишней. Стоит лишь напомнить, что выбор поддерживаемых браузеров явля- является важным шагом, который определяет способы про- проектирования не только текущих версий программы, но также и будущих ее версий. В дополнение к этим вопросам разработчик также должен задаться вопросом: Возможно ли сделать это? Как выглядят планы на будущее? Существует ли лучший путь для реализации проекта? Выяснение возможностей Этот вопрос зачастую игнорируется. JavaScript воспри- воспринимается как простой язык, которому может кто угод- угодно научиться. Это могло бы быть верным для версии 1.0 или 1.1, но 1.2 преподносит нечто совершенно новое. Начиная с этой версии, возможности JavaScript суще- существенно возросли, обеспечивая большее количество объектов для поддержки DOM-модели, а также соответ- соответствующие XML-технологии. Создание DHTML-прило- DHTML-приложения не настоль просто, может показаться на первый взгляд, а различия в версиях браузеров превращают этот процесс в весьма утомительную задачу. Планы на будущее Еще одно соображение, которое необходимо учесть, — это планы на будущее. Netscape и Microsoft выпускают
Технологии программирования на динамическом HTML Часть IV браузеры каждый год, а то и чаще, и это означает, что код, скорее всего, придется обновлять достаточно часто. В планах на будущее неплохо было бы рассмотреть все — от готовящихся стандартов до новых версий бра- браузеров. Нужно также стараться оставаться на гребне вол- волны новых технологий, дабы иметь сведения о всех воз- возникающих проблемах и ошибках программ в различных версиях. Проектирование DHTML-приложений — труд- трудная задача, однако после выполнения работы вознаграж- вознаграждение не заставит себя долго ждать. Учет API В заключение стоит обсудить тему использования в JavaScript интерфейса программирования приложений (Application Programming Interfaces, API). При создании DHTML в определенный момент может возникнуть мысль: "Должен же существовать более простой способ решения данной задачи; кто-то наверняка уже должен был делать это ранее". Скорее всего, мысль верна. Выгодная сторона JavaScript, который ни что иное как язык программирования для Internet, состоит в том, что можно обнаружить (если немножечко поискать), что другие разработчики уже создали требуемые функции, например, реализующие перемещение слоев. Кроме того, можно обнаружить, что многие разработчики уже создали объекты наподобие каскадного меню или объекты графического редактора. Не стоит в очередной раз изобретать велосипед, если обнаруживается, что кто-то уже написал нужный вам код; просто изучите этот код и воспользуйтесь им при создании своего сайта. "¦СОВЕТ ;.-....,¦ ^ •",. ..,; ¦"¦_ /'' Приложение А содержит ссылки на хорошие сайты, которые содержат полезную информацию по JavaScript API. Проектирование меню При проектировании DHTML-меню возникают доста- достаточно очевидные вопросы, например, какие меню и пункты в нем необходимы, и какие должны обеспечи- обеспечиваться функциональные возможности. К тому же, по- потребуется решить вопрос по поводу оформления меню. Какие планируются цвета и размеры? Насколь длинной должна быть строка меню, и вообще, где меню будет отображаться? Все это вопросы, на которые придется ответить, что- чтобы потом применять соответствующее форматирование и стили для создания желаемого вида сайта. Для наше- нашего примера меню поставим перед собой следующие цели: Работа только с Internet Explorer. Серая строка меню в верхней части окна браузера. Две опции меню: "Go" и "Help". Меню "Go" будет содержать три ссылки на популяр- популярные сайты для разработчиков под браузеры Netscape и Microsoft. Меню "Help" будет содержать один пункт "About", после выбора которого должно отображаться диало- диалоговое окно с информацией о меню. Диалоговое окно "About" будет содержать изображе- изображение и кнопку, закрывающую окно. Определение слоев Первая вещь, которая будет сделана в плане создания нашего меню — это определение слоев и самой строки меню. Для этого можно использовать комбинацию HTML и CSS. В HTML будут применяться дескрипто- дескрипторы <div> для задания слоев и дескрипторы <table> для определения диалогового окна. Будут также использо- использоваться дескрипторы <а> для работы с событиями щел- щелчков на пунктах меню. Код раздела <body>, реализую- реализующий меню, содержится в листинге 24.1. . Одним из важных моментов при создании любого JavaScript-приложения является повторное использова- использование кода; в этом примере повторно используется часть кода из главы 23. Читатель увидит несколько знакомых имен функций и функциональных возможностей. По- Поскольку планируется, что меню будет поддерживаться только в Internet Explorer, код выяснения типа браузера здесь отсутствует, однако если требуется поддержка Navigator, требуется заменить функцию на ту, которая использовалась в листинге 23.9 главы 23. Как видно из листинга 24.1, для каждого из слоев определяются id и name. Это позволяет применять сти- стили так, чтобы можно было управлять видом и представ- представлением этих слоев. Для установки стилей требуется не- несколько определений. Ниже приведен соответствующий список: • Запрещение подчеркивания дескрипторов <а>, Определение цвета и расположения строки меню. Определение цвета и расположения пунктов "Go" и "Help" в меню. Определение цвета, расположения и сокрытия "Go" и "Help" в меню. Определение цвета, расположения и сокрытия диа- диалогового окна "About". Листинг 24.2 содержит определения таблиц стилей, которые потребуются для форматирования.
Меню и панели инструментов DHTML Глава 24 Листинг 24.1. Определение слоев в HTML <body bgeolor="#ffffff" link="#000000" vlink="#000000" alink="#O00000" onload="checkBrowser( <div name=Mmenubar" id="menubar"X/div> <div name="go" id="go"> <a href="javascript:void@)" onmousedown="changeState('helpmenu','hidden'); changeState('gomenu','visible')"> Go</a> <div name="help" id="help"> <a hre?="javascript:void @) " onmousedown="changeState< ' gomenu " , ' hidden ' ) ;changeState ( ' helpmenu ' , 'visible ' ) "> Help</a> div name=" gomenu" id="gomenu"> <ahre?="http: / /developer. netscape . com" > DevEdge</a> <hr size="l"> <a href="http://www.mozilla.org"> Mozilla.org</a> <hr size="l"> <a href="http://msdn.microsoft.com"> MSDN</a> div name=" helpmenu" id="helpmenu"> <a hre?="javascript:void @)" onclick="changeState{ 'helpmenu', 'hidden'); changeState( 'about' , 'visible ' ) "> About. . .</a> <div name="about" id="about"> <table border="> <tr> <td> <img src="info-icon.gif"width=2" height=2"> </td> <td> This DHTML Menu was created by R. Allen Wyke for JavaScript Unleashed. </td> </tr> <tr> <td colspan=" align="right"> <form name="f orml"> <input type="button" value="Close" onclick="changeState('about', 'hidden1)"> <form> </tr> </table> </body> Листинг 24.2. Определение стиля для меню. top: о,- " ; width: 100%; <style type="text/css"> <!-- /* Глобальные стили */ /* Свойства меню */ а{ #help{ text-decoration: none; background-color : #c0c0c0; ',) position: absolute; right: 0 ; /* Свойства устанавливающие фон целого иен» */ too- О- #шепиЬаг{ , ' background-color: #c0c0c0; left: 0; #go{ position: absolute; background-color: #c0c0cO; left: 0;
Технологии программирования на динамическом HTML Часть IV position: absolute; top: 0; /* Свойства активного меню, скрытого вплоть ло щелчка */ #gomenu { background-color: ttcOcOcO; left: 10; position: absolute; top: 20; visibility: hidden; width: 80; #helpmenu{ background-color; #c0c0c0; right: 10; position: absolute; top: 20; visibility: hidden; width: 80; I ,/* Свойства диалогового окна About */ #about( background-color: gray; border: 2px solid black; height: 50; left: 100; position: absolute; top: 50; visibility: hidden; vertical-align: left; width: 200; </style> Теперь, когда практически все ясно и слои определе- определены, самое время воспользоваться динамизмом DHTML. Обработка действий Первая вещь, которую необходимо сделать в динамичес- динамической части меню — это выяснить, является ли браузер, выполняющий запрос, браузером Internet Explorer. Для этого запишем короткий оператор if, который будет вы- выдавать сообщение для браузеров, отличных от Internet Explorer: if(navigator.userAgent.indexOf("MSIE") == -1){ alert ("This menu is supported in Internet ""Explorer" ) ; window.back(); J Несложно заметить, что если браузер — не Internet Explorer, код выдаст сообщение, которое отправит пользователя обратно на страницу, с которой он при- пришел. Как и в коде из главы 23, объявляется ряд глобаль- глобальных переменных String для установки layer и style для браузеров Internet Explorer. Значения этих переменных устанавливаются после загрузки страницы в функции checkBrowser(), которая выглядит следующим образом: var layer =* new String () ; var style = new String () ; function checkBrowser(){ layer = ".all"; style = ".style"; 'J Последняя необходимая часть кода — обработка со- сокрытия и отображения слоев. Если посмотреть внима- внимательнее, можно увидеть, что это — тот же самый код, который применялся в главе 23, только немного упро- упрощенный. function changeState(layerRef, state){ eval ("document" + layer -f " ['" + layerRef + "']" + style + ".visibility = "' 4- state + Это завершающий код части <script> проектируемо- проектируемого меню. Полностью эта часть приводится в листинге 24.3. Листинг 24.3. Код для реализации меню. <script type="text/javascript" ,language=" JavaScriptl . 2"> // Глобальные переменные, var layer = new String() ; var style = new StringO/ // Это браузер Navigator? if(navigator.userAgent.indexOf("Nav") != -1){ alert ("This menu is not supported in '-¦Navigator") ; window.back(); i / / Установка переменных слоя и сфиля . function checkBrowser () { layer = ".all"; style = ".style"; I // Изменить состояние. function changeState(layerRef, state){ eval ("document" + layer + "['" + layerRef + '" ' ] " + style + " .visibility = ' " + state + 1 </script> Использование меню Как только написание кода для меню завершено (лис- (листинг 24.4), его можно загрузить в браузер для тестиро- тестирования. Меню должно иметь вид, показанный на рис. 24.1. Как видно из рисунка, CSS позволяет размещать
Меню и панели инструментов DHTML Глава 24 пункты меню в самой верхней сроке окна браузера и запрещать подчеркивание ссылок. Кроме того, стоит обратить внимание, что определение элемента menubar позволяет изменять размеры и оставляет серый фон для меню. 5 Ja»«5cnpl (Meoihn) - Micmioll Inlcirar ?крГо ' r>/¦: 41" • :; РИСУНОК 24.1. Меню, загруженное в браузер. Листинг 24.4. Полный исходный код реализации меню. <htanl> <head> <ti tle>JavaScript Unleashed</title> <script type="text/javascript" language="JavaScriptl.2"> < ! — // Это браузер Navigator? if (navigator .userAgent. indexOf ("MSIE")= -1) { alert ("This menu is supported in Internet ^Explorer"); window . back () ; I / / Глобальные переменные var layer = new String () ; var style = new String () ; // Установка переменных слоя и стиля, function checkBrowser () { layer = ".all"; style = ".style"; / / Иэменить состояние . function changeState {layerRef, state){ eval < "document" + layer t " | ' ' + layerRef + ' ¦ ] " + style + 1 + state + "'") ; </script> <style type="text/css"> <> — /* Глобальные стили */ text-decoration: none; /* Свойства установки фона целого меню */ #menubar{ background-color: #c0c0c0; left: 0 ; position: absolute; top: 0 ; width: 100%; ' Свойства меню */ #help{ background-color: #c0c0c0; position: absolute; right : 0 ; top: 0 ; 1 #go{ background-color: #c0c0c0; left: 0; position: absolute; top: 0 ; /* Свойства активного меню, скрытого вплоть до щелчка */ ttgomenu background-color: #c0cOc0; left: 10; position: absolute; top: 2 0; visibility: hidden; width: 80; ') #helpmenu( backgr ound- color : #c0c0c0; right: 10; position: absolute; top: 20; visibility: hidden; width: 80; 1 /* Свойства диалогового окна About ' #about{ background-color: gray; border: 2px solid black; height: 50; left: 100; position: absolute; top: 50; visibility: hidden; vertical-align: left; width: 200; </style> </head> <body bgcolor="#ffffff" link="#000000" vlink=" #000000" alink="#000000" onload="checkBrowser{)"> <div name="menubar" id="menubar"X/div> <div name="go" id="go">
Технологии программирования на динамическом HTML Часть IV <а hre?="javascript: void(O)" onmousedown="changeState(¦helpmenu', 'hidden') changeState('gomenu','visible')"> Go</a> <div name="help" id="help"> <ahref=" javascript: void @)" onmousedown="changeState( 'gomenu','hidden' changeState <¦ helpmenu', 'visible') "> Help</a> <div name="gomen <ahr DevEdge</a> <hr size="l"> <a hre Mozilla. org</a> <hr size="l"> <a hr< MSDN</a> <dlv name="helpme <a hre onclick="changeState('helpmenu','hidden'); changeState('about1, 'visible') "> About...</a> <div name="about" id="about"> <table border="> <tr> <td> <img src="info-icon.gif" width=2" height=2"> </td> <td> This DHTML Menu was created by R. Allen Wyke for JavaScript Unleashed. </td> </tr> <tr> <td colspan=" align="right"> <?orm name="forml"> <input type="button" value= onclick="ehangeState('about','hidden')"> <form> </tr> </table> </body> </html> После щелчка на пункте меню "Go" в левом верхнем углу всплывает меню ссылок на сайты. Как показано на рис. 24.2, эти URL-ссылки отображаются и в строке со- состояния браузера. Последним пунктом меню является пункт "Help". При нажатии на него появляется опция "About", в ре- результате выбора которой отображается диалоговое окно, показанное на рис. 24.3. la Я ! r •- : ц ¦"':¦.¦ | ¦ . ¦ ¦ РИСУНОК 24.2. Щелчок Ю пункте меню "Go". РИСУНОК 24.3.Диалоговое окно "About". Описание дополнительных возможностей Теперь, когда создано меню, несомненно, захочется расширить его возможности. Ниже приведен список пунктов, после реализации которых можно получить усовершенствованные возможности для создания ваших собственных DHTML-меню. Можно также посетить са'йт DevEdgc Netscape (http://developei где имеется свободный доступ к объекту Menu. Поддержка браузера Navigator. • Щелчок вне области всплывшего меню должен зак- закрывать его. Изменение позиции диалогового окна "About". Создание каскадных меню.
Меню и панели инструментов DHTML Создание инструментальных панелей Создание инструментальных панелей — одна из лучших вещей, которой можно научиться, имея дело с DHTML. При этом, вероятно, придется задействовать все свои способности, чтобы заставить инструментальную панель работать и взаимодействовать с другими инструменталь- инструментальными панелями желаемым способом. Формирование инструментальной панели требует не только использо- использования JavaScript, но также CSS и слоев. Ключевая про- проблема состоит в определении внешнего вида инструмен- инструментальной панели и способов ее функционирования. Затем можно приступать к проектированию размеще- размещения, кода и стиля. Применение событий Первое, что может потребоваться при проектировании инструментальных панелей — это события. В приложе- приложении, подобном браузеру, при нажатии кнопок и пере- пересечении их курсором мыши видно, что эти события вызывают изменения состояния кнопки. Для начала стоит построить инструментальную па- панель, г:одо(шую инструментальной панели браузера. Эта панель будет выглядеть и функционировать как новые инструментальные панели из Internet Explorer 3+ и Navigator 4+. Что должно происходить? Первое, что необходимо, — это задокументировать, что должно происходить в инструментальной панели. От- Откройте окно браузера и понаблюдайте, как изменяется состояние кнопок при проходе по ним мышкой и при нажатии на них. На рис. 24.4—24.6 показано, изменение состояний кнопок в браузере Navigator 4. -Щ Na visitor 4.'Й8 read and figft :•:-:= ^U. РИСУНОК 24.4. Обычная инструментальная панель. Н есложно заметить, что существуют три состояния, которые потребуется смоделировать. Когда пользова- пользователь переводит курсор мыши на кнопку, необходимо Глава 24 сгенерировать событие для выполнения определенной задачи. Кроме того, необходимо восстановить первона- первоначальное состояние кнопки, когда пользователь убирает мышку с кнопки без нажатия на нее. ¦ с A PI РИСУНОК 24.5. Прохождение мышки над кнопкой. l&Vwaon «О»|еп]-ЗЮ№¦ НаЦсдр» ян 'Netscape* . NETSCnl'K j ШШШШШШ Navigatoi rigjst С |954-ДИй М< N М.08 т' pffi РИСУНОК 24.6. Нажатие на кнопку инструментальной панели. Что может происходить? В перспективе совершенствования разработки под Web могут быть созданы все необходимые функциональные возможности для инструментальной панели. Существуют события для перемещения курсора мыши на элемент и с этого элемента, а также для нажатия и отпускания кноп- кнопки. С помощью свойства Image.src, которое может заме- заменять одно изображение на странице на другое, можно смоделировать перемещение курсора мыши и нажатие кнопок. Это свойство обеспечит визуальные эффекты. Для кнопок потребуется также выполнять опреде- определенные задачи. Для этого будет использоваться событие onClick в дескрипторе <а>. Если пользователь нажима- нажимает на кнопку, щелчок захватывается и обрабатывается. Ниже приведен список используемых кнопок вместе с их функциями.
Технологии программирования на динамическом HTML Часть IV • Back. Эта кнопка моделирует кнопку "Back" или "Previous" браузера. Будут использоваться разные ме- методы для работы в Internet Explorer и Navigator с целью демонстрации того, как можно создавать нуж- нужные программы с учетом разных браузеров. • Forward. Эта кнопка моделирует кнопку "Forward" или "Next". Будут использоваться разные методы для работы в Internet Explorer и Navigator с целью демонстрации того, как можно создавать нужные программы с учетом разных браузеров. • Ноте. Эта кнопка моделирует кнопку "Ноте" в бра- браузерах Navigator. Internet Explorer данный метод не поддерживает. • Reload/Refresh. Эта кнопка моделирует кнопку "Reload" или "Refresh" браузера, которая приводит к повторной обработке и визуализации текущей стра- страницы. При помощи метода Date.getTime() будет ото- отображаться загрузка страницы. • Find. Эта кнопка моделирует опцию меню Edit -» Find, которая обеспечивает поиск текста в окне бра- браузера. Internet Explorer этот метод не поддерживает. • Print. Эта кнопка моделирует кнопку "Print" браузе- браузера — вызов диалогового окна Print для печати теку- текущей страницы. В дополнение к перечисленным шести кнопкам, бу- будет также использоваться форма с текстовым полем, которое позволяет вводить URL и щелкать на кнопке "Go" для загрузки URL в окно браузера. Теперь, когда выяснены все требования, приступим к реализации приложения. Будет рассматриваться как создание изображений, так и написание кода. Описание проблем проектирования Прежде чем приступать к написанию какого-либо кода, следует принять несколько решений относительно спо- способов записи и хранения кода. Большинство функцио- функциональных возможностей меню можно включить в HTML- дескрипторы — не такое существенное увеличение объема кода. Однако, функциональные возможности, которые предоставляет пример, могут быть задейство- задействованы и в другом месте, потому стоит прибегнуть к бо- более модульному подходу. Хранение кода До начала создания приложения необходимо решить, где будет храниться код. Здесь следует опираться на то, ¦что именно конструируется. Для текущего приложения весь код будет храниться в рамках HTML-документа. Если сайт располагается во множестве мест, тогда код лучше хранить во внешнем JavaScript-файле (с расши- расширением js). Модульное программирование Спланируем это приложение как можно более модуль- модульным, чтобы код при необходимости мог использовать- использоваться в другом месте. Для этого придется создать множе- множество функций, обрабатывающих информацию. Для приложения можно выделить три различных набора функциональных возможностей: ¦• Image State Change (Изменение состояния изображе- изображения). Эта функция, вызываемая в методе rolllmage(), будет отвечать за изменение изображения при пере- перемещении на него курсора мыши либо при нажатии кнопки. • Button Processing (Обработка кнопки). Эта функция, вызываемая в методе process(), будет выполнять за- задачи, возложенные на кнопку. Когда пользователь нажимает на кнопку, эта функция реагирует соот- соответствующим образом. • URL Handling (Обработка адресов URL). Эта фун- функция, вызываемая в методе takeBrowser(), будет брать данные, введенные в форму, и направлять браузер в указанное расположение. Создание изображений В отличие от других приложений, для Web-приложения потребуется обеспечить максимум компонентов, кото- которые могли бы погрузиться в любой интерфейс. Поми- Помимо подобъектов объекта Form, необходимо создать все собственные изображения и интерфейсные компонен- компоненты. Из-за характера задачи также потребуется обеспе- обеспечить версии изображений для событий прохождения курсора мыши по изображению и нажатых состояний кнопок. Ранее упоминалось, что кнопка на инструменталь- инструментальной панели должна изменить свое состояние, при пе- перемещении по ней курсора мыши, а также в ситуации, когда она нажата. Для работы примера возникает необ- необходимость в следующих изображениях: • Normal. Изображение по умолчанию. • Rollover. Значение по умолчанию, отображаемое с белой рамкой толщиной в 1 пиксел слева и сверху и серой рамкой толщиной в 1 пиксел справа и снизу. '• Pressed. Значение по умолчанию, отображаемое с се- серой рамкой в 1 пиксел слева и сверху, и с белой рам- рамкой в 1 пиксел справа и снизу. Написание HTML-кода Первое, что будет создаваться — это HTML-код, кото- который содержит макет инструментальной панели. Суще- Существует несколько компонентов для интерфейса проек- проектируемой инструментальной панели (см. рис. 24.7).
tr-geffimeQ (reload v^njca^^n)- 9505192 РИСУНОК 24.7. Проектируемый интерфейс. С иелью упрощения будем использовать таблицы для хранения и упорядочения кнопок. Таблица будет содержать три строки с шестью ячейками в верхней строке и по одной ячейке во второй и третьей строках. Фон таблицы будет серый, а документа — белый. Первая строка таблицы будет содержать изображе- изображения, составляющие инструментальную панель. Каждое изображение окружается дескрипторами <а>, чтобы можно было перехватывать события нажатия мыши. В настоящее время Navigator не позволяет использовать такие события в дескрипторах <img>, хотя Internet Explorer это разрешает, так что придется предусмотреть некоторую кодовую оболочку. Ниже показан пример одной ячейки изображения. <td align="center"> <а href="javascript:process('back') " onmouseup="rolllmage('0' , ' up') " onmousedown="rolllmage('0','down')" onmouseout="rolllmage('0','out')" oranouseover="rolllmage('0','over')"> <img border=" src="back.gif" width=4" height=4" alt="Back"X/a> </td> Листинг 24.5. HTML-часть панели инструментов. Меню и панели инструментов DHTML Глава 24 Во второй строке инструментальной панели содер- содержится текстовое поле, в котором пользователь будет вво- вводить URL. Когда пользователь нажимает кнопку "Go", браузер начинает загружать URL. HTML-код для этого —¦ простой дескриптор <form>. Кнопка использует обра- обработчик событий onClick(), чтобы вызвать функцию, ко- которая перенаправляет браузер на соответствующий URL. Атрибут colspan применяется для корректного раз- размещения ячейки по ширине всей таблицы. HTML-код выглядит так: <td colspan="> <form name="netsite"> <Ь> Location: <input type="text" size=0" value="Enter a URL here" name="where"> <input type="button" value="Go" onclick="takeBrowser(this. form> "> </form> </td> Последняя строка всего лишь содержит результаты вызова метода getTime() экземпляра объекта Date. Это делается для того, чтобы пользователь мог видеть рабо- работу кнопки "Reload". Когда пользователь нажимает "Reload", числовое значение, отображаемое в этой ячей- ячейке, изменяется, подтверждая фактическую перегрузку страницы. HTML-код для этой строки следующий: <td colspan="> Result of Date. getTime () (reload verification) : <script type="text/javascript" language=" JavaScript!.. 2"> <! — document, write ( (new DateO) .getTime ()); </script> </td> Три строки в комбинации с дескриптором <body> составляют всю интерфейсную часть инструментальной панели. Листинг 24.5 показывает, что у нас уже имеет- имеется к настоящему моменту. <body bgcolor="#ffffff"> <table border="l" cellpadding=" cellspacings" align="center" bgcolor="#c0c0c0"> <tr> <td align="center"> <a href="javascript:process('back')" onmouseup="rolllmage('0','up')" onmousedown="rolllmage(' 0 ' , 'down')" onmouseout="rolllmage(' 0 ' ,'out')" onmouseover="rolllmage(' 0 ' , 'over')"> <img border=" src="back.gif" width=4" height=4" alt="Back"X/a> </td> <td align="center"> <a href="javascript:process('forward')" onmouseup="rolllmage (' 1', 'up')" oranousedown="rolllmage('1','down')" onmouseout="rolllmage('1','out')" onmouseover="rolllmage('1','over')"> <img border=" src="forward.gif" width=4" height=4" alt="Forward"X/a>
Технологии программирования на динамическом HTML Часть IV </td> <td align="oenter"> <а href =" j avascript: process {' home' >" onmouseup="rolllmage{'2','up')" onmousedown="rolllmage {' 2' , ¦ down' ) " onmouseout="rolllmage('2','out')" onmouseover="rollltnage(' 2' , • over') "> <img border=™ src="horoe. gif" width=4" height=4" alt="Home"X/a> </td> <td align="center"> <a href="j avascript: document. location. reload < \" onmouseup="rollImage('3','up')" onmousedown="rolllmage(" 3' , r down')" onmouseout="rolllmage('3','out')" onmouseover="rolllmage('3",'over') "> <img border=" src="reload.gif" width=4" height=4" alt="Reload"X/a> </td> <td align="center"> <a href="javascript:process ('find')" oranouseup="rollImage('4','up')" onmousedown="rolllmage (M',' down')" onmouseout="rolllmage <' 4' ,'out')" onmouseover="rolllmage('4','over')"> <img border=" src="search.gif" width=4" height=4" alt="Search"X/a> </td> <td align="center">- <a href="} avascript: process (' print')" onmouseup="rolllmage('5','up')" onmousedown="rolllmage|'5','down1)" onmouseout="rolllmage{' 5','out1) " onmouseover="rolllmage('5','over')"> <img border=" src="print.gif" width=4" height=4" alt="Print"X/a> </td> </tr> <tr> <td colspan="> <form name="netsite"> <Ь> Location: <input type="text" size=0" value="Enter a URL here" name="where"> <input type="button" value="Go" onclick="takeBrowser (this.form) "> </form> </td> </tr> <tr> <td colspan="> Result of Date . get Time ( ) (reload verification) : <script type="text/javascript" language=" JavaScriptl .2"> <! — document. write ( (newDate (> ) . getTime (> ) ; II—> </script> </tr> </table> </body> Реализация rollover-эффектов для изображений Для реализации rollover-эффектов для изображений используется объект Image, который, надо признать, ограничивает применимость приложений до браузеров,, поддерживающих JavaScript 1.1. Прежде всего рассмот- рассмотрим свойство src, которое позволяет изменять изобра- изображение. Как видно в HTML-коде из листинга 24.5, каж- каждый из дескрипторов <а>, обрамляющих изображение, вызывает функцию roillmagc(), которая будет опреде- определена в данном разделе. Вначале потребуется объявить все используемые изображения. Поскольку планируется использовать раз- различные состояния, лучше всего сохранить их в масси- массиве. Это позволит обращаться к изображениям в массиве
Меню и панели инструментов DHTML и в документе с помощью тех же самых индексных зна- значений. Например, на первое изображение в документе можно ссылаться через массив document.images таким образом: document.images [0] Если хранить изображения версий "нажатия" и "кур- "курсор понерх изображения" в двух разных массивах с од- одной и той же индексацией [0], то для выполнения под- подмены изображений в функцию можно передавать только одну переменную позиции. Ввиду того что требуется также восстановить предыдущее состояние изображение (значение по умолчанию), возникает необходимость в объявлении трех массивов. Ниже показан код для созда- создания этих массивов и для записи изображений в них: // Массив для хранения изображений версий // "нажатия" var overling = new Array () ; overlmg[0] = new ImageB4,24); overling [1] = new Image B4,24); overling [2] = new Image B4,24); overlmg[3j = new Image B4,24); overlmg[4] = new ImageB4,24); overling[5] = new Image B4,24); // Массив для хранения изображений версий // "курсор поверх изображения" var downlmg = new Array О ; downlmgtO] = new ImageB4,24); downlmg[1] = new Image B4,24); downlmg[2] = new Image B4,24); downlmg[3] = new ImageB4,24); downlmg[4] - new ImageB4,24); downlmg [5] = new Image B4,24); // Массив для хранения изображений по ,'/ умолчанию var def aultlmg i= new Array () ; defaultImg[0] := new ImageB4,24) ; defaultlmg[l] := new ImageB4,24); defaultlmg[2J = new ImageB4,24); def aultlmg [3] •= new Image B4,24) ; def aultlmg [4] ¦= new ImageB4,24); def aultlmg [5] = new Image B4 ,24) ; // Загрузка over «-изображений overtmg[0].src = "back-over.gif"; overling[1] .src = "forward-over.gif"; overling [2]. src = "home-over.gif"; overling[3] .src = "reload-over.gif"; overling[4] .src = "search-over.gif"; overling[5] . src = "print-over.gif"; .// Загрузка down-изображений downlmg[0].src = "back-down,gif"; downlmg[1] .src = "forward-down.gif"; downlmg[2].src = "home-down.gif"; downlmg[3].src = "reload-down.gif"; downlmg[4].src — "search-down.gif"; downlmg[5].src = "print-down.gif"; // Загрузка изображений ПО умолчанию defaultImg[0].src = "back.gif"; defaultlmg[l].src = "forward.gif"; defaultlmg[2] .src = "home.gif"; ,1 1-158 Глава 24 defaulting [3].src = "reload.gif"; defaultlmg[4].src = "search.gif"; defaultlmg[5].src = "print.gif"; Сейчас необходимо определить функцию. Это гораз- гораздо проще, чем можно было ожидать. Функция будет принимать два параметра. Первый параметр — индекс обрабатываемого изображения. Вызов функции, содер- содержащийся в дескрипторе <а>, передает числовое значе- значение, которое представляет его расположение в докумен- документе. Например, для первого изображения потребуется передать 0, для второго — 1 и т.д. Помните, что нуме- нумерация этого списка начинается с нуля, поэтому перво- первому изображению соответствует индекс 0. Второй параметр — это тип rollover-эффекта. Для нашего примера возможны четыре типа: over, out, up и down. Переданное значение анализируется в операторе switch и выполняется соответствующая подмена изобра- изображения с использованием свойства src экземпляров объекта Image — как в документе, так и в массивах. Полное определение функции выглядит следующим об- образом: function rolllmage(img,type){ switch(type){ case "over": document.images[img] .src = overImg[img].src; break; case "out": document.images[img].src = defaultlmg[img].src; break; case "up": document.images[img].src = defaultlmg[img].src; break; case "down": document, images [img] .src = downlmg [ img] .src; break; I 1 Приведенный код обеспечивает необходимую реали- реализацию rollover-эффектов для изображений. Реализация поля адреса Во второй строке примера для инструментальной пане- панели находится текстовое поле, которое позволяет пользо- пользователю вводить URL, после чего нажимать "Go" для переадресации браузера. Как было показано в HTML- коде, эта кнопка обращается к функции takeBrowser() и передает ей объект this.form. Как только функция вызвана, она будет использовать переданную ей ссыл- ссылку на объект Form, присвоит ее переменной и обратит- обратится к значению текстового поля. Затем для изменения страницы, загруженной в настоящий момент в браузер, задействуется свойство location.href, и, таким образом, браузер переадресуется на введенный пользователем новый адрес URL.
Технологии программирования на динамическом HTML Часть IV Эта функция не выполняет проверку ошибок, поэто- поэтому, если пользователь вводит некорректное значение, браузер просто сообщает о невозможности загрузки стра- страницы. Из показанного ниже кода видно, что к значению текстового поля обращаются через имя поля, опреде- определенное в атрибуте name. function takeBrowser(ref) { var form = ref; * location.href = form.where.value; 3 Обработка событий, связанных с кнопками Последняя необходимая функция будет отвечать за соб- собственно обработку. Эта функция имя которой process(), принимает один параметр. Параметр будет вычислять- вычисляться в операторе switch для шести возможных кнопок. Кнопки "Find" и "Ноте" в Internet Explorer не рабо- работают, поэтому необходимо возвращать сигнальное диа- диалоговое окно, сообщающее об этом факте. Существует также ряд других функций, которые реализуются по- разному в браузерах Navigator и Internet Explorer; им также потребуется уделить внимание. Введем перемен- переменную, которая будет сообщать о том, является ли дан- данный браузер браузером Internet Explorer. Это логическое значение будет храниться в переменной isIE, которая будет проверяться в первой строке кода функции. Код для данной функции выглядит следующим образом: function process (item) { var isIE = new Boolean (navigator .userAgent. indexOf ("MSIE") != -1) ; switch(item){ case "find": if(isIE){ alert ("Internet Explorer does not wsupport this method") ; >elseI window.find(); ) break; case "print": window. print (),° break; case "home": if(isIE) { alert("Internet Explorer does not wsupport this method") ,' }else{ window.home(); ) break; case "reload": document.location.reload(); break; case "forward": if (isIE){ history.forward(); )else{ window.forward() ; j break; case "back": if(isIE){ hi story, back () ; felse{ window. back () ; ) break; Проверка результатов На данный момент рассмотрены все HTML- и JavaScript- коды, поэтому теперь можно протестировать получен- полученное приложение. Окончательный код содержится в ли- листинге 24.6, а рис. 24.8 и 24.9 демонстрируют rollover- эффекты для кнопок. При тестировании программы наблюдайте за изменениями строки, содержащей теку- текущее время, она должна изменяться после щелчка на кнопке "Reload". Результат нажатия на кнопки "Find" и "Print" очевидны, поскольку при этом всплывают диа- диалоговые окна. Если требуется проверить кнопки "Forward" и "Back", загрузите несколько страниц в бра- браузер, тем самым обеспечив переходы браузера вперед и назад. Листинг 24.6. Полный исходный код для инструментальной панели. <html> <head> ¦<t it le> JavaScript Unleashed</title> <script type="text/javascript" language="JavaScriptl.2"> // Массивы для хранения изображений var overling = new Array { ) ; overling[01 = new ImageB4,24) overling [1] = new Image B4,24)' overling[2] ш new Image B4,24) overling [3] — new ImageB4,24) overlmg[4] = new Image B4,24) overling[5] = new ImageB4,24) var downlmg = new Array () ; downlmg[0] = new ImageB4,24) downlmg[1] = new ImageB4,24)
Меню и панели инструментов DHTML Глава 24 downlmg[2] = new Image B4,24) ; downlmg[3] = new ImageB4,24) ; downlmg[4j = new ImageB4,24) ; downlmg[5] = new Image B4,24) ; var defaultlmg = new Array () ; defaultImg[O] = new Image B4,24) ;; def aultlmg [1] - new Image B4,24) ; de?aultlmg[2] = new Image B4,24) ; defaultlmg[3] - new Image B4,24) ; def aultlmg [4] ¦ new Image B4 ,24) ; defaultlmg[5j = new Image B4,24) ; // Загрузка изображений в массивы overlmg[0] .sro = "back-over.gif"; overling [1].src overling [2].src overlmg[3].src everImg[4].src overling [5] .src "forward-over.gif" ; "home-over.gif" ; "reload-over.gif" ; "search-over.gif"; "print-over.gif"; пришедшего обытия. downImg[0].srс = "back-down.gif"; downlmg[l].src = "forward-down.gif"; downlmg[2].src = "home-down.gif"; downlmg[3].src = "reload-down.gif"; downlmg[4] . src= "search-down.gif"; downlmg[S].src = "print-down.gif"; defaultlmg[0].src = "back.gif"; defaultlmg[l] .src = "forward.gif"; defaultlmg[2].src = "home.gif"; clefaultImg[3] .src ¦ "reload.gif"; defaultlmg[4].src = "search.gif"; defaultlmg[5].src ¦ "print.gif"; // Изменение состояния в зависимости functionr oil Image (img,type) { switch(type){ case "over" : document, images [img] .sre = overling [img] .src; break; case "out" : document.images[img].src = defaultlmg [img] .sre; break; case "up" : document, images [img] .src = defaultlmg [img] .src,: break; case "down": document, images [img] .src = downlmg [img] .src; break; J // Обработка адреса URL, введенного в текстовом поле function takeBrowser (ref) { var form = ref; location.href = form.where.value; I // Обработка нажатий кнопок function process(item){ var isIE = new Boolean (navigator .userAgent. indexOf ("MSIE") != -1) ; switch(item){ case "find": if(isIE)( alert ("Internet Explorer }else{ window.find() ,- 1 break; case "print" : i does not support this method") ;
Технологии программирования на динамическом HTML Часть IV window, print () ; break; case "home": if (isIE){ alert ("Internet Explorer does not support this method") ; }else{ window. home <) ; } break; case "reload": document.location, reload ( ) ; break; case "forward": if (isIE){ history.forward{) ; window. forward (); } break; case "back" : if<isIE){ history.back () ; >else{ window. back ( > ; } break; > </script> </head> <body bgcolor="#ffffff"> <table border="l" cellpadding=" cellspacing="O" align="center" bgcolor="#cOcOcO"> <tr> <td align="cet\ter"> <a href="javascript:process< 'back') " onmouseup="rolllmage ( ¦ 0 ¦ , ' up ¦ ) " onmousedown=" roll Image ( ' О ' , ' down" ) " onmouseout="rolllmage ( '0 ' , ' out ' ) " onmouseover="rolllmage< ¦ 0 ' , ' over' ) "> <img border=" src="back.gif" width=4" height=4" alt="Back"X/a> </td> <td align="center">- <ahref="javascript:process{ 'forward') " onmouseup="rolllmage ( ' 1 ' , ' up ' ) " onmousedovm="rolllmage ( ¦ 1 ¦ , ¦ down ' ) " onmouseout="rolllmage( ' 1 ' , ' out " ) " onmouseover="rolllmage ( ' 1 l , * over * ) "> <img border=" src=" forward.gif" width=4" height=4" alt="Forward"X/a> </td> <td align="center"> <ahref=" javascript:process( 'home') " onmouseup="rolllmage ( ' 2 ' , ' up " ) " onmousedown="rolllmage( ' 2 ' , ' down " ) " onmouseout= " rolllmage ( " 2 ' , ' out ' ) " onmouseover="rolllmage ( ' 2 ' , ' over ' ) "> <img border=" src="home.gif" width=4" height=4" alt="Home"X/a> </td> <Td align="center"> <ahref="javascript:process< 'reload') " onmouseup="rolllmage ( ' 3 ' , ' up'' ) " onmousedown="rolllmage ( ' 3 ' , ' down ' ) " onmouseout="rolllmage ( '3 ' , ' out ' ) " onmouseover="rolllmage < ' 3 ' , ' over ' ) "> <img border=" src="reload.gif" width=4"height=4" alt="Reload"X/a> </td> <td align="center"> <ahref=" javascript:process < ' find') "
Меню и панели инструментов DHTML Глава 24 onmouseup="rolllmage{'4',' up'>" onmousedown="rolllmage('4','down')" onmouseout="rolllmage('4' ,'out')" onmouseover="rolllmage('4','over1)"> <img border=" src="search.gif" width=4" height=4" alt="Search"X/a> </td> <td align="oenter"> <a href="javascript :process( 'print') " onmouseup="rolllmageA5l,"up")" oranousedown="rolllmage(' 5','dovm')" onmouseout="rolllmage('5','out') " onmouseover="rolllmage<'S','over')"> <img border=" src="print.gif" width=4" height=4" alt="Print"X/a> </td> </tr> <tr> <td colspan="> <form name="netsite"> <b> Location: <input type="text" size=0" value="Enter a URL here" name="where"> <input type="button" value="Go" onelick="takeBrowser {this.form) "> </form> </td> </tr> <tr> <td colspan="> Result of Date . getTime () (reload verification) : <script type="text/javascript" language="JavaScriptl.2"> <! — document.write((new Date()) .getTime()); II—> </script> </td> </tr> </table> </body> </html> . . ¦ ¦ . ¦:¦¦-. РИСУНОК 24.8. Курсор мыши над кнопкой. Резюме В главе уделялось внимание подробностям, связанным с реализацией DHTML на сайте. Полученные знания РИСУНОК 24.9. Нажатие кнопки инструментальной панели. помогут приступить к созданию динамических страниц с использованием не только JavaScript, но также и дру- других HTML-элементов и CSS.
Взаимодействие с другими технологиями В ЭТОЙ ГЛАВЕ Подключаемые модули браузера Элементы управления ActiveX Java-аплеты LiveAudio Вне зависимости от того, хорошо ли вы знакомы с программированием на JavaScript или же пока являет- является новичком в этом деле, вы, скорее всего, еще не рас- раскрыли всех функциональных возможностей данного языка. Web-разработчики знают, что существует множе- множество других технологий, таких как Java-аплеты и эле- элементы управления ActiveX, которые можно использо- использовать для усиления впечатления, производимого сайтом. В главе рассматриваются несколько технологий по- подобного рода, а также их использовании в JavaScript. Некоторые из технологий предназначены только для определенных браузеров, тем не менее, и они являют- являются допустимыми. Подключаемые модули браузера Современные браузеры собственными средствами могут поддерживать содержимое всего лишь нескольких видов файловых форматов, к которым относятся тексты (вклю- (включая HTML) и изображения. Однако для работы вне Web-браузеров люди для решения различных задач постоянно используют множество других файловых форматов. Например, большинство прикладных программ об- обработки текстов имеют собственные файловые форма- форматы (например, формат .doc файла Microsoft Word), так же дело обстоит и с приложениями электронных таблиц, презентаций, мультимедиа и т.д. Если Web-браузер под- поддерживает различные файловые форматы, появляется возможность построения различного содержимого, в любой момент доступного через Web, не говоря уже о применении Internet для новых и увлекательных спосо- способов представления информации. Однако, для Netscape (или любой другой компании) создание в браузере собственной поддержки всех ис- используемых файловых форматов было бы непрактичным из-за слишком больших затрат денежных и временных ресурсов. Так что для большинства браузеров решение отдается в пользу технологии подключаемых модулей. |дамЕЧАниеч.. ;> *' "¦ ''¦„;, '¦> \: ¦• *¦¦'-" Хотя в главе обсуждаются различные технологии, с которыми JavaScript может взаимодействовать, здесь не будет говориться о применении этих технологий на Web-страницах. Например, не будет детально рассмат- рассматриваться использование дескрипторов <applet>, <object> и <embed>, а также их атрибутов. Для получения дополнительной информации по этой теме посетите сайты Microsoft Developer Network (htfp:// msdn.microsoft.com) либо Netscape DevEdge (http:/ / developer.netscape.com), а также сайт V/ЗС-консор- циума (http://www.w3.org). Подключаемые модули и MIME-типы Подключаемые модули идентифицируют тип передава- передаваемых им данных в зависимости от MIME-типов. Иден- Идентифицируя тип данных, подключаемый модуль может выбирать соответствующий способ их обработки. MIME является стандартом Internet, который опре- определяет способы передачи файловых форматов (не тек- текстовых) в почтовых сообщениях Internet. (Более подроб- подробная информация может быть найдена в Internet Requests For Comment (RFCs) 1521 и 1522.) Толчком для созда- создания упомянутого стандарта послужила необходимость передачи через электронную почту не только докумен- документов, содержащих простой текст. MIME теперь позволяет прикладным программам электронной почты работать с отформатированным текстом, файлами приложений и другими типами файлов, расширяющих сообщения. Стандарт MIME может обрабатывать любой файловый
Взаимодействие с другими технологиями формат, включая текст, PostScript, файлы изображений, звуковые, видео- и сжатые файлы. MIME-ТИПЫ определяют тип содержимого и специ- специфический подтип различных файловых форматов. Это стоит пояснить на примере. MIME-ТИП для файлов с расширением .wav (Microsoft audio) определяется как audio/x-wav. audio описывает звуковой тип или категорию поддерживаемых файлов, а Х-Wav — определенный тип файла (или подтип), под- поддерживаемый с учетом требований браузера, для интер- интерпретации файлов .wav. После начала работы браузер начинает просматри- просматривать все установленные подключаемые модули и при- присваивает MIME-типы соответствующим подключаемым модулям, которые могут прочитать их. При выявлении в процессе просмотра MIME-типа браузер загружает присвоенный (или зарегистрированный) подключаемый модуль в память, и MIME-тип обрабатывается этим подключаемым модулем. MIME-тип может отображать- отображаться одним их трех способов: Встроенный (inline). Появляется на странице вмес- вместе с другим содержимым. Размер области подклю- подключаемого модуля определяется предварительно уста- установленными значениями параметров height и width дескриптора, используемого для загрузки этого под- подключаемого модуля. Полный (full). Подключаемый модуль занимает все окно браузера за исключением инструментальных панелей. Скрытый (hidden). Подключаемый модуль выполня- выполняется в фоновом режиме (подобно некоторым аудио- модулям). Определение устанавливаемых подключаемых модулей Определение того, какие в клиентском браузере уста- установлены подключаемые модули и какие поддерживают- поддерживаются MIME-типы, дает разработчику Web-страницы мно- множество возможностей по управлению содержимым, предназначенным для отображения пользователям. На- Например, один из сценариев разработки мог бы выглядеть так: "Если пользователь имеет подключаемый модуль, отображается страница со всеми соответствующими MIME -типами, а иначе — альтернативное содержимое". В большинстве браузеров (но только не в Internet Explorer) JavaScript помогает выполнить это. JavaScript-браузеры содержат два встроенных объек- объекта, которые дают весьма полезную информацию о под- подключаемых модулях и MIME-типах, поддерживаемых браузером клиента: Глава 25 navigator.plugins. Этот объект, представляющий со- собой свойство объекта Navigator, — массив всех под- подключаемых модулей, в настоящий момент установ- установленных в браузере клиента. Поскольку такой массив фактически является подобъектом объекта Navigator, он имеет следующие свойства: name. Имя подключаемого модуля (например, Shockwave). filename. Имя файла подключаемого модуля. description. Описание подключаемого модуля (обеспечивается поставщиком модуля). length. Количество элементов в массиве. [...]. Массив объектовтшеТурев, которые может прочесть подключаемый модуль. navigator.mimeTypes. Это свойство, представляющее собой подобъект объекта Navigator, — массив всех mimeTypes, поддерживаемых в браузере клиента. По- Подобъект имеет следующие свойства: type. Имя MIME-типа (например, audio/x-wav). description. Описание MIME-типа (обеспечивает- (обеспечивается поставщиком модуля). enabledPlugin. Подключаемые модули, которые могут прочесть данный MIME-тип. suffixes. Расширения имен файлов, с помощью которых идентифицируются MIME-типы (на- (например, .wav для MIME-типа audio/x-wav). Рас- Расширения отделяются друг от друга запятыми. Объект Plugins Используя эти объекты в сочетании с JavaScript, мож- можно довольно быстро определить, установлен ли подклю- подключаемый модуль. Ниже приведен пример, в котором вы- выясняется наличие подключаемого модуля Macromedia Shockwave. Если данный подключаемый модуль при- присутствует, файл загружается и отображается. Если нет, отображается альтернативная информация: var DesiredPlugin = navigator.plugins["Shockwave"]; // ссылка на имя объекта подключаемого модуля if (DesiredPlugin) { document, write ( ' <embed src="mymovie.dir" wheight=40" width=20">' > ; }else{ document.write(' <img src="movietitle.jpg" ^*height=40" width=20">') ; ) Объект navigator.plugins также содержит метод refresh(), который заставляет браузер находить все установленные подключаемые модули и соответствующим образом под- подстраиваться. Если с методом refresh() используется ар-
Технологии программирования на динамическом HTML Часть IV гумент true (например, navigator.plugin.refresh (true)), то наличие нового подключаемого модуля регистрируется без выхода и перегрузки окна браузера. При использовании navigator.plugins.refreshltrue] бра- браузер перегрузит только страницы, которые изменяются из-за изменения подключаемого модуля. Однако, по умолчанию (если метод refresh|) не используется) браузер перегружает все страницы, которые содер- содержат любые типы файлов. Объект MimeTypes Используя новый объект navigator.mimeTypes, можно достаточно быстро определить, поддерживает ли брау- браузер клиента определенный MIME-тип. В следующем примере выясняется, поддерживает ли браузер MIME- тип application/x-director (для кинофильма Macromedia Director Shockwave). Далее следует логическое продол- продолжение, как в предыдущем примере: var DesiredMimetype = navigator.mimeTypet"application/x-director"]; if (DesiredMimetype) ( document.write('<embed src="mymovie.dir" k»height=40" width=20">1 > ; >else{ document:. write < '<imgsrc="movietitle. jpg" 1-height=40" width=20">r > ; :i Можно также использовать простой цикл JavaScript для отображения всех MIME-типов, поддерживаемых клиентским браузером: for (var i = 0; i < navigator . mimeTypes. length ; i++) I document.write(navigator. mimeTypes[i].type + СОВЕТ ., Дополнительная информация об этих объектах может быть найдена в главе 9. Элементы управления ActiveX ActiveX-технология Microsoft также предоставляет ме- методы внедрения в HTML-документы элементов управ- управления (в данном случае — OLE-приложения Microsoft). Элемент управления OLE, внедренный таким образом в HTML, становится элементом управления ActiveX, ко- который распознается Microsoft Internet Explorer 3+ и Netscape Navigator, оснащенным подключаемым моду- модулем ActiveX. ^ПРИМЕЧАНИЕ *J.^Lr^ "^ v'Z^iT..! -.«." ^ В настоящее время эти элементы управления поддер- поддерживается только на платформе Windows. Однако Microsoft работает над методами расширения техно- технологии ActiveX для других поддерживаемых платформ, включая MacOS, Solans и HP-UX. Если такой браузер загружает HTML-документ с эле- элементом управления ActiveX, который еще не присут- присутствует в хост-машине браузера, браузер загружает его с сервера. Так должно происходить, потому что эти эле- элементы управления в действительности являются OLE- объектами и могут выполняться только в браузерах на совместимой с OLE-приложением платформе, такой как Microsoft Windows. Это создает проблему переносимо- переносимости для тех пользователей браузеров, которым требует- требуется обратиться к такому документу. Понятие элемента управления ActiveX Если ActiveX — новый термин, рассмотрим следующие два варианта. В зависимости от того, на что вы будете опираться, каждый из вариантов будет более приемле- приемлемым. Если следовать от Web или Java, элемент управ- управления ActiveX — это ответ Microsoft на Java-аплеты, мини-приложения, которые могут выполняться внутри окна браузера. А если опираться на разработку баз дан- данных Windows, элементы управления ActiveX можно считать Web-эквивалентами и VBX (элементами управ- управления Visual Basic), VCL (компонентами Delphi) или OCX (элементами управления OLE). Как будет показа- показано далее, связь с OCX — нечто гораздо большее, неже- нежели простое сравнение. Прежде чем компания Microsoft решила, что ActiveX — наилучший термин с точки зрения маркетинга, тот же элемент управления назывался OCX. Элементы управ- управления ActiveX были встроены в OLE-технологию, доступ- доступную в течение нескольких лет. Однако, следует отметать, что элементы управления ActiveX требуют меньше затрат,, чем стандартные элементы управления OLE. Поскольку для элементов управления ActiveX не применяются ссылки или внедрения объектов, как, например, для документа Word, часть OLE-технологии из ActiveX была удалена. В результате остался один компонент — более быстрый и занимающий меньше места. Основная причина появления Java связана с необхо- необходимостью достижения переносимости для всех сред. В противоположность этому, главное достоинство элемен- элементов управления ActiveX — это совместимость с домини- доминирующей на рынке операционной системой Windows 9x, NT и, в настоящий момент, Windows 2000. Совмести- Совместимость проявляется в том, что те же самые элементы уп- управления ActiveX, которые применяются на Web-стра- Web-страницах, могут использоваться любым Windows-приложе- Windows-приложением либо инструментальным средством, работающим с OCX. Причина заключается в использовании Windows большинством пользователей Web; в конечном итоге элементы управления ActiveX становятся естественным расширением рабочего стола.
Взаимодействие с другими технологиями Ниже приведен пример HTML-кода для встраивания элемента управления OLE (в данном случае OLE-объек- OLE-объекта ButtonCtrl) в HTML-документ: <object id="MyButton" width="83" height=7" classid="CLSID:3472D900-5A27-llCF-8Bll- OOAAOOC00903"> <ра*ат name="ExtentX" VALUE=196"> <param name="ExtentY" VALUE=14"> </object> Строка для атрибута classid — значение CLSID-ВХО- да средства управления OLE ButtonCtl, в системном ре- реестре Windows. К счастью, нет необходимости записы- записывать такой код вручную. Код в приведенном примере генерировался приложением ActiveX Control Pad от Microsoft. ActiveX Control Pad, в дополнение к возмож- возможностям ручного редактирования текста HTML-докумен- HTML-документов, обеспечивает полуавтоматическое размещение и создание сценариев для элементов управления ActiveX. При использовании приложения ActiveX Control Pad для размещения элемента управления ActiveX в HTML-до- HTML-документе можно вызвать список всех элементов управле- управления OLE, доступных в системном реестре Windows. Все элементы управления OLE доступны авторам HTML-1 документов. " РЕСУРС ' i • - : ¦* "'" ¦ ЩЖШ Более подробное описание ActiveX Control Pad выходит за рамки данной книги. ActiveX Control Pad можно выг- выгрузить из Developer Network Online Microsoft. Его же можно отыскать по адресу http://msdn.microsoft.com/ workshop/components/dtctrl/setupdcp.exe. Элементы управления ActiveX имеют набор собы- событий, каждое из которых связано с частью кода JavaScript (или, скорее, JScript). Например, элемент управления ButtonCtl содержит событие onClick, аналогичное собы- событию типа Button в HTML-форме. Элемент управления ActiveX может быть произвольно сложным; например, элемент Calendar содержит следующие события, кото- которые могут задаваться в коде сценария: AfterUpdate, BeforeUpdate, Click, DblClick, KeyDown, KeyPress, KeyUp, NewMonth и NewYear. Ниже показан пример кода события для элемента управления ActiveX: <script type=" text/javascript" ?or="MyButton" event="onClicle() "> alert('hello universe1); II—> </script> Реализация защиты ActiveX содержит систему цифровых подписей, встро- встроенную в его компоненты. Разработчик компонент может "поставить" цифровую подпись на элементе управления ActiveX, чтобы гарантировать пользователям заявленное Глава 25 происхождение программного обеспечения. Эта цифро- цифровая подпись отображается в Internet Explorer при загрузке элемента управления. Пользователь, глядя на нее, реша- решает, продолжать ли загрузку. Если элемент управления не имеет цифровой подписи, пользователи уведомляют- уведомляются о его неизвестном происхождении и выполняется запрос на подтверждение загрузки. Можноустановитьпроцесс"автоматическогоодобре- ния"для поставщика, которому вы доверяете, чтобы все компоненты из этого источника одобрялись авто- автоматически. Доступ с помощью JScript Как только элемент управления ActiveX будет встроен в документ, можно добавлять JScript-код и работать с ним, как с любым другим объектом JScript, т.е. устанав- устанавливать свойства, реагировать на события или обращаться к методам элементов управления ActiveX. Сразу же после начала использования элементов управления ActiveX становится ясно, что в присоеди- присоединении к ним JScript-кода нет ничего сверхъестествен- сверхъестественного. Если знать свойства и методы элемента управле- управления, для создания сценария можно воспользоваться обычным JScript-редактором. В листинге 25.1 показан пример JScript-кода для реализации ответа на метод Click командой кнопки. Листинг 25.1. Использование JScript для взаимодействия сэлементом управления ActiveX. <html> <head> <title> JavaScript Unleashed</title> <script type="text/javascript"> <! — function loadBox() ( alert ("The Great Question") ; </script> <script type="text/javascript" for="ConanandButtonl" event="Click() "> var msg = "She loves me" ; var altMsg = "She loves me not" ; if (CoiranandButton 1 .Caption = msg) { CommandButtonl.Caption = altMsg; window.defaultStatus = altMsg; }else{ if(CommandButtonl.Caption = altMsg){ CommandButtonl.Caption = msg; window.defaultStatus = msg; } J .11—> </script> </head> <body onload="loadBox()"> <object id="CommandButtonl" width="98" height=2"
Технологии программирования на динамическом HTML Часть IV classid="CLSID:D7053240-CE69-HCD-A777- 00DD01143C57"> <param name="VariousPropertyBits" value=68435483"> <param name="Caption" value="She loves me"> <param name="Size" value=096;678"> <param name="FontCharSet" value="> <param name="FontPitchAndFamily" value="> <param name="ParagraphAlign" value="> <param name="FontWeight" value="> </object> </body> </html> Поскольку дескриптор <object> не позволяет добав- добавлять обработчики событий в виде его параметров, для добавления параметров for и event потребуется прибег- прибегнуть к альтернативному синтаксису обработки событий Microsoft, который предполагает использование расши- расширенного синтаксиса дескриптора <script>. Подобным способом можно сообщить JScript, для чего предназна- предназначены объект и событие внутри дескрипторов <script>. Сценарий, реализующий задачу из листинга 25.1, выг- выглядит следующим образом: <script type="text/javascript" for="CommandButtonl" event="Click() "> <! — var msg = "She loves me"; var altMsg = "She loves me not" ; if(CommandButtonl.Caption == msg){ CommandButtonl.Caption = altMsg; window.defaultStatus = altMsg; >else{ if(CommandButtonl.Caption == altMsg){ CommandButtonl.Caption = msg; window.defaultStatus = msg; </script> Java-аплеты Одной из наиболее полезных особенностей JavaScript является возможность взаимодействия с Java-аплетами, JavaScript-сценарии могут вызывать Java-методы, иссле- исследовать и изменять Java-переменные и управлять Java- аплетами. В свою очередь, Java-аплеты могут обращаться к JavaScript-методам, свойствам и структурам данных. ^ПРИМЕЧАНИЕ .Vs" '7 ¦¦•,.' -*¦..''. ,"?ч'' *- ' - Этот метод доступа к Java-аплетам называется LiveConnect и поддерживается только браузерами Navigator. Доступ к Java из JavaScript: JavaScript-сценарии взаимодействуют с Java-аплетами, выполняющимися на HTML-странице, путем обраще- обращения к членам (методам и полям) Java-объектов аплета. Любой метод Java, объявленный с модификатором public, доступен из JavaScript, и любое поле Ja\a, объяв- объявленное как public, доступно для управления и измене- изменения. Первый шаг организации связи JavaScript с Java- аплетом — это создание ссылки на аплет. Как только этот шаг выполнен, становится возможным обращаться непосредственно к любому из членов аплета. Примечание ¦¦¦ ¦ * - • LiveConnect — это Netscape-технология на стороне клиента, которая обеспечивает непротиворечивое уп- управление данными между тремя главными клиентски- клиентскими средами Navigator — подключаемыми модулями, Java и JavaScript. Дополнительную информацию отно- относительно LiveConnect можно найти на сайте DevEdge Netscape по адресу http://developer.netscape.com. Технология LiveConnect позволяет JavaScript связы- связываться с Java следующими способами: Прямые вызовы методов Java Управление Java-аплетами Управление подключаемыми модулями Java Ссылки на аплеты Аплеты, выполняющиеся в документе, в JavaScript до- доступны через массив document.applets. Например, на первый аплет, определенный в текущем документе, из JavaScript можно ссылаться как на document .applets[O]. На тот же аплет можно также ссылаться как на document, applets ["appletName"J или просто document.appletName, если его имя было определено в дескрипторе <applet>. Имя аплета можно указать в дескрипторе <applet>, присвоив значение атрибуту name. Например, дескрип- дескриптор <applet name="myApplet" code="testApplet. class" width=00" height=00" mayscriptX/applet> создает аплет класса testApplet с именем myApplet. Если это первый аплет на странице, он будет называться document.applets[O], document.appletsf'appletName"] или document. myApplet. JavaScript-сценарии могут также ссылаться на Java- аплеты, выполняющиеся в других фреймах того же окна браузера. Например, если Java-аплет выполня- выполняется в фрейме с именем framel, к нему можно обращать- обращаться из фрейма того же уровня следующим образом: parent, framel. document.myapplet. Подключаемые модули Java В JavaScript каждый подключаемый модуль на Web- странице считается элементом массива embeds. Напри- Например, document.embedsfO] — первый встроенный объект на странице.
Взаимодействие с другими технологиями Если подключаемый модуль связан с классом Java netscape.plugin.Plugin, к его статическим переменным и методам можно обращаться тем же способом, который был продемонстрирован в предыдущем разделе для до- доступа к переменным, методам и свойствам Java-аплета. Доступ к JavaScript из Java Для доступа к JavaScript-методам, свойствам и структу- структурам данных из Java-аплета необходимо сначала импор- импортировать пакет javascript Netscape. Это делается с ис- использованием следующего синтаксиса: import netscape.javascript.* netscape.javascript определяет класс JSObject и объект исключения JSException. Следует предоставить аплету доступ к JavaScript, объявив атрибут mayscript (без аргументов) для дескриптора <applet>. Это предот- предотвратит доступ из аплета к JavaScript на странице без знаний, имеющихся у разработчика. Если атрибут mayscript не будет объявлен, возникнет ошибка. Прежде чем обращаться к JavaScript, необходимо полу- получить дескриптор окна Navigator. Для этого воспользуйтесь методом getWindow класса netscape.javascript.JSObject: winHandle = JSObject.getWindow(this) winHandle — это переменная типа JSObject. Для обращения к объектам и свойствам JavaScript необходимо применять метод getMember класса netscape.javascript.JSObject. Это можно сделать, вызвав getMember для поочередного обращения к каждому объекту JavaScript. Однако, в первую очередь следует удостовериться в существовании дескриптора окна JavaScript (он получается при помощи метода getWindow). Для вызова JavaScript-методов можно воспользовать- воспользоваться методами call и eval класса netscape.javascript. JSObject. Повторим, что необходимо применить getWindow для получения дескриптора окна JavaScript, и затем при помощи call или eval обратиться к методу JavaScript. Синтаксис выглядит так: • JSObject.getWindow().call("methodName", arguments) methodName — имя вызванного JavaScript-метода, a arguments — массив аргументов, передаваемых в данный метод. • JSObject.getWindow().eval(" expression") expression — JavaScript-выражение, вычисляемое для JavaScript-метода. Использование JSObject Поскольку сложный JavaScript-объект (например, мас- массив или объект Window) отражаются в Java в виде объек- объектов типа JSObject, важно знать, как управлять этими Глава 25 объектами и извлекать информацию их них. Когда JSObject представляет массив JavaScript, полезно уметь исследовать отдельные элементы массива, а когда JSObject вводит Window, Document, History или подоб- подобные им JavaScript-объекты, неплохо уметь проверять их свойства. На первый взгляд может показаться заманчивым способ обхода проблемы путем разложения объектов JavaScript на более простые объекты. После такого раз- разложения полученные элементы можно было бы послать Java как наборы простых объектов, где они бы переве- перевелись в Java-объекты String, Double и Boolean. Главный недостаток такого подхода, помимо боль- большого объема дополнительной работы, состоит в том, что этот способ не оставляет никакой возможности для об- обработки объектов переменного размера. Если неизвест- неизвестно заранее, сколько элементов будет содержать массив, не найдется способа передать каждый отдельный эле- элемент в Java-метод, поскольку Java-методы принимают набор аргументов, устанавливаемый в процессе компи- компиляции. Вероятно, лучше будет просто передать Java сложные объекты JavaScript и научиться работать с ними. ' ПРИМЕЧАНИЕ "Г Убедитесь, что атрибут mayscript присутствует в дес- дескрипторах <applet> для всех аплетов, которые пла- планируется использовать с JSObject. Без этого аплет не получит доступа к объектам и свойствам JavaScript. Эта мера была разработана для того, чтобы позволить авторам HTML-кода включать непроверенные Java-an- леты в свои страницы без переживаний на предмет того, что эти аплеты получат доступ к потенциально критичной информации, предназначенной только для JavaScript. В качестве конкретного примера предположим, что необходимо использовать JavaScript в качестве GUI для Java-аплета построения графика по точкам. Ниже пока- показаны объявления переменных и функций. <soript type="text/javascript"> <!-- var xvals = new Array () ; var yvals = new Array () ; function addPoint(x, y) ( xvals[xvals.length] = x; yvals[yvals.length] = y; ¦) function plotPoints() { document.myApplet.plotPoints(xvals, yvals); </script> а также HTML-форма с обработчиками событий: <form> <input type=text name="xval">
Технологии программирования на динамическом HTML 4acn»IV <input type=text name="yval"> <br> <input type=button value="Add Point" onclick="addPoint(form.xval.value, form.yval.value)"> <br> «Cinput type=button value="Plot Points" onclick="plotPoints()"> </form> Можно собрать координатные пары (х, у), исполь- использующие два текстовых входных поля и функцию addPoint() и послать их аплету в одном большом пакете с помо- помощью функции plotPoints(). Это позволяет передавать аплету произвольное чис- число точек, из которых требуется составить график, но требует разложения массивов точек в Java. Java-метод plotPointsQ из этого примера дает хорошее представле- представление о том, что можно сделать с объектами JSObject. Код выглядит следующим образом: public void plotPoints (JSObject xvals, JSObject yvals){ Double length = (Double) xvals.getMember("length"); int n = Math.round(length.doubleValue()); for (int i = 0; i < n; i++) { try{ String sx = (String) xvals.getSlot(i) ; String sy = (String) yvals.getSlot (i) ; Double x = new Double (sx) ; Double у = new Double (sy) ,- doPlot(x, y) ; )catch(NumberFormatException e) System.err.println("Illegal point *¦» specification") ; Рассмотрим более подробно части программы, стро- строка за строкой. public void plotPoints(JSObject xvals, JSObject yvals) Этот метод получает два объекта JSObject — массив х-координат и массив у-координат. Обратите внимание, что массивы JavaScript, даже числовые, в Java не пока- показываются как массивы одного из встроенных числовых типов Java. Если функция вместо этого записывается с сигнатурой: public void plotPoints(double[] xvals, doublet] yvals) то любая попытка вызова ее из JavaScript потерпит не- неудачу. Вы окажетесь связанными с объектами JSObject вместо требуемых числовых массивов. Double length = (Double) xvals. getMember i ("length"); Вызов getMember() — первый шаг, необходимый для преобразования аргументов из формы, в которой они были переданы, к используемой форме. Метод getMemberQ применяется для получения свойства length одного из объектов массива (оба массива имеют одну и Ту же длину). getMemberQ возвращает универсальный Object (базовый класс для всех Java-объектов), однако его требуется затем привести к соответствующему типу. Известно, что свойство length массивов JavaScript — чис- числовое, а JavaScript-числа отражены в Java как Double, поэтому объект, возвращенный getMember(), приводит- приводится к Double. Обратите внимание, что в выбранном здесь типе нет никакой гибкости; числа, доступные из JSObject дол- должны приводиться к Double. Только когда числовые зна- значения JavaScript передаются непосредственно в Java как аргументы функций, они могут появляться как Java- типы, отличные от Double. int n = Math.round(length.doubleValue ()); Хотя этот оператор не содержит непосредственно JSObject, он демонстрирует полезное выражение для преобразования JavaScript-числа в используемый в Java тип числа. Программисты часто будут получать объек- объекты Double, тогда как им нужнее другие типы, следова- следовательно, их необходимо будет преобразовать. В этом слу- случае метод doubleValueQ объекта Double используется для получения фактического числового значения, а метод roundQ пакета Math — для получения целого числа, наиболее приближенного к данному значению. String sx = (String) x.getSlot (i) ; .String sy = (String) у .getSlot (i) ; Внутри цикла возникает необходимость в способе получения числового значения каждого элемента объек- объектов JSObject, представляющих массивы xvals и yvals. Здесь метод getSlotQ применяется для извлечения от- отдельного элемента массива с данным индексом. Метод getSlot() берет индекс в качестве аргумента и возвращает объект JavaScript, соответствующий этому индексу. getSlot(), подобно getMember(), возвращает универсаль- универсальный Java-объект, поэтому его снова потребуется приве- привести к нужному типу. Как было сказано, массивы xvals и yvals содержат JavaScript-строки, следовательно, в дан- данном случае требуется использовать Java-тип String. На первый взгляд это может показаться странным, т.к. элементами массива обычно являются числа, но String — действительно то, что нужно в данном случае. Вспомните, что значения массивов были получены из текстовых полей ввода HTML-формы. В JavaScript, если строка выглядит как число (состоит полностью из. цифр), это еще не делает ее числом. Double х = new Double(sx); Double у = new Double (sy)/ Нам понадобится способ преобразования строк, ко- которые выглядят как числа, в фактически числа, и для этого больше всего подойдет упоминаемый ранее кон-
Взаимодействие с другими технологиями струкгор Double. Ему потребуется String в качестве ар- аргумента, и он вернет объект Double, соответствующий значению с плавающей точкой двойной точности, пред- представленному String. Если String не представляет число- числового значения, применяется NumberFormatException, поэтому операторы будут вложены в блок try. В случае возникновения исключения попытка помещения точки в график прерывается и начинается следующая итера- итерация цикла. doPlot(x, у) ; Имея значения координат (х, у), извлеченные из JSObject, осуществляется вызов гипотетического низко- низкоуровневого метода рисования по точкам. Хотя исчерпывающее изучение класса JSObject вы- выходит за пределы этой книги, еще один пример помо- поможет продемонстрировать несколько его методов. Пред- Предположим, что требуется добавить к аплету метод, составляющий график по всем точкам, которые пользо- пользователь уже ввел в форму, и не дожидающийся нажатия кнопки "Plot Points" пользователем. Метод, который показан ниже, позволяет аплету выйти в JavaScript-мир и рассматривать требуемые ему объекты JavaScript вся- всякий раз, когда это потребуется: private void getPoints(){ .// Получить окно и документ. JSObject window = JSObject.getWindow(this); JSObject document = (JSObject) window.getMember("document"); // Получить массивы точек. JSObject xvals = (JSObject) document.getMember("xvals"); ¦ JSObject yvals = (JSObject) docuemnt.getMember("yvals"); // Вызов plotPointsO plotPoints(xvals, yvals); 1 Рассмотрим более подробно строки из новых мето- методов и концепции, не применявшиеся в предыдущем при- примере. private void getPoints(){ Обратите внимание, что этот метод — private, т.е. он не предназначен для вызова из JavaScript. Обратите так- также внимание, что здесь не требуются аргументы, по- поскольку вся информация, необходимая для решения за- задачи, содержится в JavaScript. Главное достоинство примера состоит в том, что Java-аплеты могут свобод- свободно отыскивать объекты и свойства JavaScript, причем для этого не требуется никаких пользовательских дей- действий со стороны JavaScript. JSObject window = JSObject.getwindow(this); Класс JSObject содержит статический метод getWindowO, который может использоваться аплетом для получения Глава 25 JavaScript-объекта Window, соответствующего окну, содер- содержащему этот аплет. Возвращенный объект — это про- просто тот же самый объект, обозначенный как Window в JavaScript. getWindowO — особо важный и полезный метод, т.к. он является единственным способом, с по- помощью которого Java-аплет может получить "новый" JSObject (т.е. JSObject, не полученный из другого, су- существовавшего ранее, объекта JSObject) без явной пе- передачи его из JavaScript; класс JSObject не содержит конструкторов public. Аргументом для getWindowO яв- является непосредственно объект аплета. JSObject document = (JSObject) window.getMember([sql]document[sq2]); После получения объекта Window метод getMember() используется для извлечения свойства по его имени. В данном случае свойством является объект Document окна, т.е. объект, обозначенный window.document в JavaScript. Переменные xvals и yvals, как и все перемен- переменные, определенные на "верхнем уровне" JavaScript-сце- JavaScript-сценария, являются свойствами объекта Document. Слож- Сложные объекты JavaScript, такие как Document, отражаются в Java как JSObjects, следовательно, Object, возвращен- возвращенный getMember(), будет приводиться к этому типу. JSObject xvals = (JSObject) document.getMember("xvals"); JSObject yvals = (JSObject) document.getMember("yvals"); Как только получен объект Document, можно при- приступать к извлечению необходимых переменных. Для достижения этой цели еще раз применяется метод getMember(). Объекты xvals и yvals являются JavaScript- массивами, которые представляются в Java как JSObject, поэтому объекты, возвращенные getMember(), снова приводятся к этому типу. PlotPoints (xvals, yvals) ; Теперь, когда получены JSObject, представляющие массивы xvals и yvals, можно вызвать метод plotPoints() изнутри Java точно так же, как он вызывался из JavaScript. Стоит отметить два других метода класса JSObjects — call() и eval(), которые имеют следующие прототипы: public Object call(String methodName, Object argsH); public Object eval(String s) ; callO вызывает метод methodName своего объекта с аргументами, хранящимися в массиве args. Это эквива- эквивалентно запросу this.methodName(arg[0], arg[l], . . .); из JavaScript. Например, следующий код в аплете JSObject window = JSObject.getWindow(this); Object args[] = { "Hello, world!" }; window.call("alert" , args);
Технологии программирования на динамическом HTML Часть IV эквивалентен такому JavaScript-коду:' alert("Hello, world!"); Метод eval() объекта вычисляет строку аргумента как выражение JavaScript. Вычисление производится в пределах контекста объекта. Замена последней строки в предыдущем примере на window.eval(alert("Hello, world!')"); обеспечивает тот же самый результат. Обратите внима- внимание на использование одинарных кавычек внутри двой- двойных. Трансляция типов данных Одним из наиболее трудных и запутанных аспектов в вызовах Java-методов из JavaScript является получение совпадения типов аргументов, переданных Java, с типа- типами аргументов, ожидаемых Java-методом. Если два на- набора аргументов не соответствуют друг другу, происхо- происходит сбой в обращении к функции и выдается сообщение об ошибках, в котором говорится, что JavaScript не мо- может найти Java-метод, который бы ожидал передавае- передаваемые аргументы. Java — строго типизированный язык (т.е. каждая пе- переменная имеет совершенно определенный, объявлен- объявленный тип), поэтому для всех Java-методов должно быть объявлено заранее, сколько аргументов они ожидают, какого типа и каком порядке. В Java-программе любая попытка вызова метода с последовательностью аргумен- аргументов, которая в точности не соответствует объявленной последовательности для данного метода, приводит к ошибке на этапе компиляции. JavaScript, напротив, имеет гораздо менее строгий контроль типов и, как интерпретируемый язык, должен осуществлять всю необходимую проверку во время вы- выполнения. JavaScript-переменные не имеют объявленно- объявленного типа; фактически, их можно не объявлять вообще, а вместо этого просто ссылаться на них. Той же самой JavaScript-переменной может быть присвоена строка в. одном операторе, целое число в следующем операторе и массив — еще в одном. Как JavaScript-объекты преобразовываются в Java- объекты при передаче их методам Java? Откуда Java зна- знает, как найти Java-тип, который точно соответствует структуре JavaScript-объекта? Коротко говоря, он вооб- вообще этого не делает. Вероятно, такого объекта не суще- существует. Если объект не относится к одному из опреде- определенных исключений, Java не обязательно имеет класс, который в точности отражает тип JavaScript-объекта, поэтому он просто присваивает это значение типу по умолчанию (JSObject), предназначенному представлять JavaScript-объекты в Java. К счастью, в упомянутые выше исключения входят некоторые из наиболее часто используемых типов дан- данных, в том числе и три основных типа данных JavaScript: строки, числа и логические переменные. JavaScript-строки (т.е. строковые константы и перемен- переменные, которым в последнюю очередь были присвоены строки) появляются в Java как экземпляры Java-типа String. JavaScript-числа (числовые константы и перемен- переменные, которым в последнюю очередь были присвоены целые или действительные числовые значения) преоб- преобразуются в Java-объекты Double. Логические перемен- переменные JavaScript (true и false) станут Java-объектами Boolean. Другой особый случай касается JavaScript-объектов, которые являются оболочками для Java-объектов. Такие объекты просто "изымаются из оболочек" и преобразовы- преобразовываются в исходные Java-типы. Хотя сей факт в настоящее время не задокументирован, существует дополнительная гибкость при передаче JavaScript-чисел непосредствен- непосредственно Java-методам. Попытка сделать вызов наподобие document.myApplet.setNumberC.7); окажется успешной, если аплет myApplet содержит ме- метод с сигнатурой public void setNumber (type x) ; где type — один из следующих типов: Double, double, float, long, int, short, char или byte, хотя документация гласит, что приемлем только Double. В случаях, когда в аплете имеется много перегруженных методов, ожида- ожидающих один из указанных выше типов, выбирается пер- первый такой метод (метод, самый близкий к началу файла исходного кода на Java). Нарушение лексикографичес- лексикографического расположения — вероятно, не лучший способ ре- решить конфликты между перегруженными методами; скорее всего, скоро будет предложен другой механизм. Предположим, что для контроля приемлемых значе- значений theText применяется метод setText(), и требуется найти способ выяснения, привел ли вызов setTextQ к успешной установке theText. Новая функция, которая возвращает логическое значение, отображающая успех или неудачу, может выглядеть следующим образом: public boolean setText(String s) { if <s.equals("Hello world!")){ // Я устал оа? этой строки. Не используйте ее. return false; ;)else{ theText = s; return true ; В JavaScript-сценарии, включающем строку
Взаимодействие с другими технологиями var changed = document, myApplet.setText ("Hello «world!") значение, возвращенное setText(), сохранится в changed. Тем не менее остается вопрос: как Java-значение Boolean,, возвращенное setText(), будет преобразовываться в JavaScript-объект? В данном случае ответ прост и инту- интуитивно понятен: Java-значение Boolean станет JavaScript- значением boolean, когда оно вернется JavaScript. Передача Java-объектов в JavaScript не всегда настоль проста — для точного перевода каждого объекта существу- существует ряд правил. Впрочем, часто все происходит именно так, как нам нужно. Java-массивы становятся JavaScript- массивами, числовые типы Java становятся JavaScript- числами, Java-значения Boolean — JavaScript-значени- JavaScript-значениями boolean, a Java String — JavaScript String. В заклю- заключение рассмотрим полный набор используемых правил для управления преобразованиями: Числовые типы Java (byte, char, double, float, int, long, short) становятся JavaScript-числами. Java-значения Boolean становятся JavaScript-значе- JavaScript-значениями boolean. Java JSObject преобразуются в свои исходные JavaScript-объекты. Java-массивы становятся JavaScript-объектами Array. Все другие Java-объекты преобразуются к JavaScript- объектам, помещенным в оболочки, и могут исполь- использоваться для обращения к первоначальным Java- объектам. При попытке преобразования JavaScript-объекта в оболочке в JavaScript-строку, число или логическое значение, вызывается метод исходного Java-объекта toString(), doubleValueO или booleanValue(), если он су- существует, и значение, возвращенное из соответствующе- соответствующего метода, становится значением преобразованного объекта. Если требуемый метод не существует, преоб- преобразование дает сбой. Обратите внимание, что Java-стро- Java-строки корректно работают в JavaScript даже при том, что> они были переданы JavaScript как объекты-оболочки. Любая попытка использовать их в контексте, в котором ожидаются JavaScript-строки, приводит к корректному преобразованию этих строк. Подробнее о Java-аплетах Выше в этой главе рассматривались способы взаимодей- взаимодействий JavaScript/Java. Теперь хорошо известно, что мож- можно сделать и, до некоторой степени, как это работает. Далее более подробно исследуется, что фактически про- происходит при вызове этих методов и свойств из различ- различных гред. Глава 25 Вызов Java-методов Предполагая, что LiveConnect включен, можно исполь- использовать следующий синтаксис для обращения к Java-ме- Java-методу: Packages . packageName.className .methodName где packageName и className — свойства объекта Packages. Имя Packages в вызовах можно опустить в пакетах Navigator по умолчанию — Java, Sun или Netscape. Напри- Например, на Java-класс java.lang.System можно ссылаться как java.Iang. System или Packages.java.lang. System. Рассмотрим пример. В приведенном ниже коде JavaScript использует доступ к Java для вывода сообще- сообщения на Java-консоль: <script type="text/javascript"> <!-- java.Iang. System.out.println ("Greetings from ^JavaScript") ; // — > </script> Установка Java-свойств Хотя это не самый хороший стиль программирования для Java-классов — предоставлять всем прямой доступ к компонентам данных (называемым также свойствами или полями), объявляя их public, но иногда бывают си- ситуации, в которых это оправдано. Когда Java-аплеты содержат поля public, у JavaScript-сценариев появляет- появляется возможность непосредственно изменять их так же, как они вызывают Java-методы public. Например, рас- рассмотрим следующий фрагмент Java-аплета: public String theText; public void setText(String s) { theText = s; > Наилучшим стилем программирования будет уста- установка текста следующим образом: document, my Applet. setText ("Hello world! ") ; Для достижения того же результата можно было бы записать: document.myApplet.theText = "Hello world!"; Те же правила, которые управляют трансляцией JavaScript-объектов в Java-объекты в процессе обраще- обращения к функции, применимы и в данном случае. Здесь имеется в виду, что таким образом могут быть установ- установлены только Java String, Double, Boolean, JSObject и примитивные числовые типы, поскольку все JavaScript- переменные первоначально отражаются в Java в виде одного из этих типов. Использование Java-пакетов Возможности взаимодействия JavaScript с Java не огра- ограничены аплетами. JavaScript-сценарии имеют также
Технологии программирования на динамическом HTML Часть IV прямой доступ к статическим методам и полям базовых Java-пакетов, они могут даже создавать новые Java-объекты. Java-пакеты доступны в JavaScript через массив Packages документа. Например, Java-naKeTJavaJang.System, исполь- используемый для консольного ввода-вывода, будет называть- называться в JavaScript Packages.java.lang. System, a Java-пакет java.lang.Math — Packages.java.lang. Math. Следова- Следовательно, для записи значения "пи" на Java-консоли мож- можно использовать следующий код: var pi = Packages.Java.lang.Math.PI; Packages . Java. lang.System.out.println("pi is: " + Pi)? Для сокращения в ссылке к трем заданным по умол- умолчанию пакетам —Java, sun и netscape — можно безопас- безопасно опустить ключевое слово Packages. To есть, в пре- пределах JavaScript-объекта Document имена Java, sun и netscape представляют собой, соответственно, альтер- альтернативные имена для Packages.java, Packages.sun и Packages.netscape. Используя эти имена, можно пере- перезаписать пример с "пи" следующим образом: var pi = Java. lang.Math. PI,- Java.lang.System.out.println("pi is: " + pi) ; Также возможно создавать новые Java-объекты ди- динамически, используя операцию new. Это удобный спо- способ обратиться к некоторьш из мощных встроенных сер- сервисных Java-классов — хэш-таблицам, стекам, векторам, датам и т.п. — без написания полного Java-аплета. В следующем примере на JavaScript создаются два Java- объекта Date, и затем они сравниваются с помощью метода after класса Date для выяснения, является ли те- текущая дата последней. var theDate = new Java. util. Date (); // текущая // дата var deadline = new Java. util. Date @0, 6, 26); II 26 июля 2000 г. if (theDate.after(deadline)) { alert ("I missed my deadline!"); )else{ alert ("Made it!") ; Управление аплетами После получения ссылки на аплет, следующим шагом будет установка связи с ним путем активизации одного из его методов. Например, если аплет имеет общедос- общедоступный метод hello(), который не содержит никаких аргументов, этот метод можно вызвать следующим об- образом: document.myApplet.hello(); Создание приведенного выше вызова из JavaScript производит такой же эффект, как вызов из Java метода hello() объекта аплета. Для еще одного примера пред- предположим, что имеется Java-аплет с музыкой из кино- кинофильма, в котором требуется включать и выключать звуке использованием JavaScript. Если аплет предостав- предоставляет методы, подобные показанным ниже, для управ- управления звуковой дорожкой кинофильма можно вызывать эти методы из JavaScript: public void soundtrackOn(); public void soundtrackOff(); Если желательно свести все управление звуковой дорожкой кинофильма к простому щелчку кнопкой мыши, можно использовать JavaScript в качестве "про- "провода" для присоединения переключателей HTML-фор- HTML-формы к Java-аплету. Следующий пример демонстрирует применение элемента form метода onClick для взаимо- взаимодействия с аплетом: <?orm> <input type="radio" checked="true" name="sound" onclick="document.myApplet.soundtrackOn()"> On <br> <input type="radio" name="sound" onclick="document.myApplet.soundtrackOff()"> Off </form> Значения для обработчика событий onClick опреде- определяют, что методы soundtrackOn() или soundtrackOff() аплета с именем myApplet вызываются всякий раз при нажатии соответствующего переключателя. В качестве более сложного примера (который иллюстрирует пере- передачу аргументов Java-методам), предположим, что ап- аплет также содержит метод с прототипом public void changeText(String s) ; который при вызове изменяет текст, отображаемый ап- аплетом, на значение, передаваемое в строке s. Если в форму добавить следующие элементы <input type="text" name="newtext"> <input type="button" value="Change Text" onclick="document.myApplet.changeText(form, newtext.value)"> пользователи смогут вводить в текстовом поле новые строки, которые будут отражаться в аплете. При нажа- нажатии кнопки "Change Text" значение текстового поля из- извлекается, преобразуется в String Java и передается как аргумент в метод аплета changeText(). Это весьма мощ- мощный инструмент. Возможность передачи JavaScript- объектов Java-методам позволяет быстро и легко конст- конструировать привлекательные графические пользователь- пользовательские интерфейсы из стандартных HTML-форм, усили- усиливая их за счет обработчиков событий JavaScript, и при- применять их для управления Java-аплетами. LiveAudio LiveAudio, неотъемлемая часть браузера Netscape Navigator, представляет собой встроенный подключаемый модуль,
позволяющий браузеру Navigator запускать звуковые файлы собственными средствами. По сути дела, Live Audio расширяет Navigator в сторону распознавания нового типа содержимого. Это означает, что большин- большинство пользователей Web теперь может свободно получать и прослушивать аудиофайлы при наличии соответству- соответствующего оборудования. Это, в свою очередь, открывает для Web-разработчика новый мир больших возможнос- возможностей — возможностей восприятия информации и развле- развлечений "через уши". LiveAudio интегрирован в среду Navigator и может легко управляться через JavaScript и LiveConnect. Эти преимущества наряду с широкой доступностью LiveAudio, требуют его детального обсуждения. Lлaвa содержит примеры LiveAudio и демонстрирует способы примене- применения JavaScript для управления им. Эта книга, вероятно, окажется последней, содержа- содержащей информацию о LiveAudio. Промышленность раз- развивается в направлении создания встроенных проигры- проигрывателей, таких как G2 Player Real и Microsoft Windows Media Player, для обработки аудио- и видеофайлов. Как утверждается на Web-сайте Netscape, LiveAudio был создан с учетом всех функциональных возможнос- возможностей LiveConnect. Это означает, что можно пользовать- пользоваться любыми преимуществами LiveConnect и JavaScript для управления внедренными (или встроенными) LiveAudio-элементами. С помощью LiveConnect JavaScript может взаимодействовать с LiveAudio, позволяя про- программно выполнять следующие действия: Создание альтернативных интерфейсов управления звуком. Задержку загрузки аудиофайла, пока пользователь не выполнит действие (например, нажатие кнопки "Play"). Создание интерфейсных кнопок с шумовыми эффек- эффектами. Обеспечение аудиорасширения для взаимодействия с пользователем. Например, можно заставить объект говорить, что он делает при нажатии или перемеще- перемещении курсора мыши поверх него. Использование JavaScript-методов JavaScript обеспечивает для LiveAudio несколько мето- методов управления, чтобы дать возможность разработчику легко управлять аудиофайлами, внедренными в Web- страницу. Для этих методов доступен JavaScript, одна- однако, где-то на странице потребуется встроить консоль LiveAudio. Взаимодействие с другими технологиями Глава 25 Рассмотрим методы управления LiveAudio через JavaScript:: ¦• play(). Включает звук. Можно определить значение цикла, подобно значению атрибута loop, с необяза- необязательным URL для звука, если исходный URL не ис- используется. stop(). Останавливает звук, если он был включен. • pause(). Пауза для звука в текущей позиции. Для продолжения воспроизведения можно использовать методы play() или pause(). start_time() и end_time(). Позволяют переустанавли- переустанавливать время начала и конца воспроизведения. Значе- Значения определяются в секундах. start_at_beginning() и stop_at_end(). Устанавливают время начала и конца воспроизведения на начало и конец звукового файла. setvol(). Устанавливает громкость звука в интервале от 0% до 100%. fade_to(). Устанавливает громкость, плавно изменяя ее от текущего значения. fade _from_to(). Позволяет определить два значения и плавно регулировать звук от одного значения к другому. ¦• IsReady(). Возвращает true, если звуковой файл заг- загружен и Готоц к воспроизведению. IsPlaying(). Возвращает true, если звук воспроизво- воспроизводится. IsPaused(). Возвращает true, если воспроизведение звукаприостановлено. GetVolume(). Возвращает текущую громкость. Эти методы обеспечиваются через свойство document. embeds, которое содержится в массиве <embeds> на те- текущей странице. Для применения одного из перечис- перечисленных методов просто обращаются к нему, используя следующий формат: document.embedName.method () ; Например, вызвать метод play() во внедренном про- проигрывателе myRadio можно с помощью такого кода: document.myRadio.play(); Воспроизведение звуков в ответ на JavaScript-события Как упоминалось ранее, JavaScript можно использовать для вызова звука в любом месте сайта. Тем не менее, зачастую наиболее пригодным местом для вызова зву-
Технологии программирования на динамическом HTML Часть IV ков, усиливающих впечатления пользователя, оказыва- оказываются JavaScript-события. Следующий пример использует эту концепцию, демонстрируя способ вызова несколь- нескольких звуков на Web-странице путем захвата и обработки событий onLoad, onUnLoad, и onClick обработчиками событий JavaScript. В этом примере (см. листинг 25.2) звук (type.wav), привязанный к нажатию клавиш, воспроизводится после загрузки страницы. Для демонстрации события onClick предполагается, что после щелчка на гиперссылке поль- пользователь слышит звук кассового аппарата, а при нажа- нажатии на кнопку — звук выстрела. Кроме того, при уходе со страницы пользователь услышит звук разбиваемого стекла. Результирующее окно браузера показано на рис. 25,1. Листинг 25.2. Управление звуками при помощи JavaScript. <html> <head> <title>JavaScript Unleashed*:/title> <script type="text/javascript"> <! — function playSound(sfile) { // Загрузка и воспроизведение аудио- // файла window. location, href=s?ile; У II—> </script> </head> <bodyonLoad="playSound("Type.wav' >" onUnLoad="playSound{ 'Glass.wav') "> <h2> Sounds on JS Events </h2> <hr> The following are examples of JS event handlers used to play sounds. <hr> <a href="#" onClick="playSound(' Cashreg.wav1) "> Click here for sound <form name="forml"> <input type="button" value="Play" onClick="playSound('Gunshot.wav')"> </form> </body> </html> Следующий пример демонстрирует способ примене- применения некоторых встроенных JavaScript-методов для уп- управления звуковыми файлами. Код, показанный в лис- листинге 25.3, позволяет загружать звук и затем управлять им с помощью нескольких кнопок. Обратите внимание на использование скрытой консоли для первоначально- первоначального вызова LiveAudio. На рис. 25.2 находится получив- получившаяся в окне браузера страница. Sounds on JS Events The fallowing are MCamplf of JS eVEU t Ъакйеге vsed w play sounds. Л1 Rm1****. РИСУНОК 25.1. Примеры вызова звуков в ответ на JavaScript события. 7 #" ^ i Г ^ ^йд^а Embedded Sounds in JavaScript Tbis document ioebdes a hidden embedded sourict, which к leaded afierlbe page-is loa-dled You я ю Ц РИСУНОК 25.2. Управление внедренными звуками с помощью JavaScript. Листинг 25.3. Управление внедренными звуками с помощью JavaScript. <html> <head> <title>JavaScript Onleashed</title> </head> <body> <h2> Embedded Sounds in JavaScript <embed mastersound name="soundl" src="test.wav" volume=00" hidden="true" autostart="false"> <hr> This document includes a hidden embedded sound, which is loaded after the page is loaded. You can use the JavaScript buttons below to control the sound.
Взаимодействие с другими технологиями <hr> <form name="forml"> <input type="button" value="Play" onclick="document.soundl.play(true)"> <input type="button" value="Pause" onclick="document.soundl.pause()"> <input type="button" value="Stop" onclick="document.soundl.stop ()"> </form> </htm.L> Резюме В главе рассматривались некоторые способы взаимодей- взаимодействия JavaScript с другими технологиями. Была пред- Глава 25 ставлена технология подключаемых модулей Netscape и объяснены различия между подключаемыми модуля- модулями, вспомогательными приложениями и MIME-типами. Здесь также обсуждались проблемы интегрирования элементов управления ActiveX с JScript. Было выясне- выяснено, что такое ActiveX-технология и как ее можно ис- использовать при создании сценариев. Кроме того, рас- рассматривались вопросы взаимодействия с Java-аплетами через LiveConnect. Глава завершилась обсуждением способов примене- применения обработчиков событий JavaScript для вызова звуков на НТМГ-странице, а также способов установки вне- внешних аудиопроигрывателеи в качестве вспомогательных приложений прослушивания аудиофайлов.
Избранные программные технологии ЧАСТЬ В ЭТОЙ ЧАСТИ 26. Гарантия работы сценариев в браузерах Netscape и Microsoft 27. Методы выяснения типа браузера 28. Навигация по сайту с использованием JavaScript 29. Формы и верификация данных 30. Персонализация и динамические страницы ¦31. Сопоставление шаблонов с помощью регулярных выражений 32. Технология манипуляции данными со стороны клиента 33. Обработка ошибок .34. Отладка 35. JavaScript и безопасность в Web
Гарантия работы сценариев в браузерах Netscape и Microsoft В ЭТОЙ ГЛАВЕ Версии языка и версии браузера Сравнительный анализ JavaScript-диалектов Ошибки Первоначальный вид JavaScript, как и всех компью- компьютерных языков, претерпел несколько изменений. Наи- Наибольшее число изменений было внесено в версии JavaScript 1.1 и 1.2. В этих версиях основные функциональные возможности постоянно модифицировались, и програм- программистам становилось все сложнее создавать JavaScript- код, который работал бы в разных браузерах. Обычно такие проблемы обходили, избегая использования тех особенностей, из-за которых возникали проблемы со- совместимости, однако проблемы JavaScript существова- существовали и в рамках базовых функциональных возможностей! Еще большую сумятицу внесла компания Microsoft, коренным образом изменившая JavaScript, дабы не покупать лицензию на ее использование. Результатом стала еще одна разновидность JavaScript — от Microsoft, получившая название JScript. В конечном итоге на JavaScript начали смотреть как на нечто очень непосто- непостоянное.. К счастью, Netscape и Microsoft признали, что Ва- Вавилонскую башню из JavaScript строить ни к чему. Они представили язык на утверждение комитету стандарти- стандартизации ЕСМА (European Computer Manufacturers Association — Европейская Компьютерная Ассоциация Изготовителей), который и собрал воедино язык ECMAScript 1.0 (ЕСМА262). Стандарт был очень быс- быстро принят как Netscape, так и Microsoft. После этого события базовые функциональные воз- возможности JavaScript стабилизировались в версиях JavaScript 1.3 и JScript 3.0. Эта стабильность сохраня- сохраняется и на сегодняшний день в JavaScript 1.4 и JScript 5.O. Проблемными областями сейчас являются не они, а ско- скорее интеграция в JavaScript новых Web-технологий, та- таких как каскадирование таблиц стилей (CSS). Из сказанного выше ясно, что JavaScript претерпел некоторые изменения, которые все еще проявляются в различиях способов создания сценариев. В главе расска- рассказывается, какие версии браузеров поддерживают функ- функциональные возможности JavaScript. Версии языка и версии браузера Возможно, вы несколько запутались во всех этих номе- номерах версий JavaScript и JScript и номерах версий брау- браузеров Microsoft и Netscape. Таблица 26.1 показывает соотношения версий языка и версий браузеров. Таблица 26.1. Соотношение версий языка и версийбраузера. Браузер Netscape Navigator Microsoft Internet Explorer Версия 2.0 3.0 4.0-4.05 4.06-4.7X 6.0 3.0 4.0^.5 5.0' 5.5 Язык JavaScript 1.0 JavaScript 1.1 JavaScript 1.2 JavaScript 1.3 JavaScript 1.4 и 1.5 JScript 1.0 JScript 3.0 JScript 5.0 JScript 5.5 Как видно из приведенной таблицы, весьма важно знать, какие браузеры будут использовать заказчики для просмотра Web-страниц. Решив в первую очередь, ка- какие браузеры будут поддерживать создаваемые Web-стра- Web-страницы, можно сберечь немалое время на разработку. С дру- другой стороны, если есть некая особая функциональная
Избранные программные технологии Часть V возможность JavaScript, которую требуется использовать на Web-странице, тогда следует выбирать браузер, со- соответствующий такой версии JavaScript, которая поддер- поддерживает необходимые функциональные возможности, либо воспользоваться методикой выяснения типа брау- браузера (см. главу 27). Сравнительный анализ JavaScript- диалектов. JavaScript был детищем Sun Microsystems. Navigator Netscape стал первым браузером, интерпретирующим язык и обеспечивающим расширенные функциональные возможности JavaScript за счет взаимодействия с под- подключаемыми модулями и средой Java. Вскоре после этого Microsoft ввела в игру JScript. Как упоминалось ранее,, JavaScript в течение первых лет своего существования претерпел достаточно много изменений. Только теперь, наконец, основные функциональные возможности JavaScript стабилизировались и язык получил возмож- возможность взаимодействовать с другими Web-технологиями. Хотя текущая версия JavaScript довольно стабильна, может потребоваться поддержка старых браузеров, а для этого очень пригодится знание сроков появления и из- изменения всех функциональных возможностей данного языка. Еще более важно помнить, что часто требуется правильное выполнение сценариев в обоих браузерах — Microsoft и Netscape. Поэтому полезно рассмотреть раз- различные JavaScript-диалекты, а также браузеры, обеспе- обеспечивающие их поддержку. JavaScript от Netscape Этот раздел состоит из пяти подразделов — по одному на каждую версию JavaScript. Каждый подраздел дета- детализирует все объекты, свойства, методы, обработчики событий, встроенные функции, операции и операторы, которые являются новыми для данной версии. Для получения наиболее актуальной информации о новых версиях JavaScript посетите Web-сайт Netscape по адресу http://devedge.netscape.com/tech/ javascript/ index.html JavaScript 1.0 Основная спецификация JavaScript 1.0 сначала поддер- поддерживалась в Netscape Navigator 2.0. Ниже приведены списки оригинальных функциональных возможностей объектов, функций, операций и операторов. Объекты Button Form Location Reset Checkbox Frame Math Select Date Document FileUpLoad Embed Функции escape eval parseFIoat Операции !! &= * *== ++ += < == > >= Операторы delete do...while for Function Hidden History Link parselnt unescape = I 1 >> for... in function if...else Navigator Option Password, Radio % %= & / 1**1 I/ 1 l= <<= <= = Submit Text Textarea Window && /= _= >>= >>> >>>= new return while with Таблицы с 26.2 по 26.4 содержат исходные свойства, методы и обработчики событий. Таблица 26.2. Свойства, поддерживаемые в JavaScript 1 .0 и следующих версиях. Свойство actioni aLinkColor appCodeName appName appVersion ibgColor checked cookie defaultChecked defaultStatus defaultValue document E elements encoding fgColor form frames hash host hostname Объект Form Document Navigator Navigator INavigator Document Checkbox, Radio Document Checkbox, Radio Window Password, Text, Textarea Frame, Window Math Form Form Document Checkbox, FileUpload, Hidden, Password, Radio, Reset, Select, Submit, Text, Textarea Frame, Window Link, Location ¦Link, Location Link, Location
Свойство Объект href tastMadifted length linkColor links LN10 LN2 location LOG10E LOG2E imethod name options parent pathname PI port protocol se/ected/ndex self search SQRT1_2 SQRT2 Status previous prototype referrer search selected self target text title top userAgent URL vlinkCotor value window Link, Location Document Form, Frame, History, Select, String, Window Document Document Math Math Document, Window Math Math Form Button, Checkbox, FileUpload, Form, Frame, Hidden, Password, Radio, Reset, Submit, Text, Textarea, Window Select Frame, Window Link, Location Math Link, Location Link, Location ¦Select Window Link Math Math Window History Date Document .Location Option Frame Form, Link Option Document Frame, Window Navigator Document Document Button, Checkbox, FileUpload, Hidden, Option, Password, Radio, Reset, Submit, Text, Textarea Frame Гарантия работы сценариев в браузерах Netscape и Microsoft Глава 26 Таблица 26.3. Методы, поддерживаемые в JavaScript 1 .0 и последующих версиях. Метод abs acos alert anchor asin atan atan2 back big blink bold blur ceil char At charCodeAt clearTimeout click close concat confirm r;os exp fixed floor focus fontcolor fonts ize forward fromCharCode get Date getDay getHours getMinutes getMonth getSeconds getTime getTimezoneOffset getYear go handleEvent indexOf italics llastlndexOf Объект Math Math Window String Math Math Math History String String String Password, Reset, Select, Text, Textarea Math String String Window Button, Reset, Submit Document, Window String Window Math Math String Math Checkbox, Password, Reset, Select, Text, Textarea String String History String Date Date Date Date Date Date Date Date Date History Password, Select String String String
Избранные программные технологии ЕМУ Метод Часть V Объект link log imatch max min open parse pew propt random round select setDate setHours setMinutes setSeconds sefTime setTimeout setYear sin small sqrt strike sub submit substring sup tan toGMTString toLocaleString toLowerCase toSource toString toUpperCase UTC write writeln Таблица 26.4. ( String Math String Math Math Document, Window Date Math Window Math Math FileUpLoad, Text, Textarea Date Date Date Date Date Frame, Window Date Math String Math String String Form String String Math Date Date String Math Date, Math String Date Document Document Обработчики событий, подцержива- емые в JavaScript 1.0 и последующих версиях. Обработчик событий Объект onBlur onChange Password, Radio, Reset, Select, Text, Textarea Select, Text, Textarea Обработчик событий Объект onClick Button, Document, Radio, Reset, Submit, Text ¦onDblClick Document onFocus Password, Radio, Reset, Select, Text, Textarea onKeyDown Document ¦onKeyPress Document onKeyUp Document onLoad Window onUnLoad Window onMouseDown Button, Document onMouseOver Link onMouseUp Button, Document onSelect Textarea onSubmit Form JavaScript 1.1 JavaScript 1.1 поддерживается в Netscape Navigator 3. Ниже приводятся списки объектов, функций, опера- операций, операторов, расширений дескрипторов и изменен- измененных (по сравнению с предыдущими JavaScript-версия- JavaScript-версиями) возможностей. Объекты Applet Area Array Boolean Функции taint Операции typeof Оператор continue Function Image MimeType Number untaint void Расширения дескрипторов В дескриптор <SCRIPT> был SRC. Object Package Plugin String добавлен атрибут • Атрибут LANGUAGE для <SCRIPT> может опре- определять версию языка. Был добавлен дескриптор <NOSCRIPT>, Поддержаны сущности JavaScript (такие как &{myVar};). Возможности • Добавлена LiveConnect — возможность связи Java и JavaScrip.
Гарантияработы сценариев в браузерах Netscape и Microsoft Глава 26 Добавлена возможность обнаружения доступных подключаемых модулей. Добавлены прототипы объектов, т.е. возможность создания свойств, которые появятся во всех объек- объектах одного и того же типа. • Добавлена возможность динамического изменения объектов Select. Добавлена возможность передачи строк между сце- сценариями в разных окнах или фреймах. Изменен способ индексации свойств Object. Если свойство определено по имени, необходимо всегда ссылаться на него по имени. Точно так же, если свойство определено через индекс, на него всегда ссылаются, используя этот индекс. eval() вместо встроенной функции стал методом каж- каждого объекта. • Добавлена возможность печати и сохранения дина- динамического HTML, сгенерированного с помощью ме- методов writeQ и writeln(), с использованием соответ- соответствующей команды из меню "File". • Изменены три встроенных функции:181ЧагЧ, parseFloat и parsclnt, каждая из которых теперь выполняется одинаково на всех платформах. • Добавлена возможность удаления объекта, устанав- устанавливая ссылку на него равной Null. • Добавлена возможность динамического сброса обра- обработчиков событий. Добавлена поддержка преднамеренного искажения данных для целей безопасности. • Добавлена возможность использования строк в каче- качестве индексов массивов. Таблицы с 26.5 по 26.7 содержат расширения свойств, методов и обработчиков событий, добавленные в JavaScript 1.1. Таблица 26.5. Свойства, поддерживаемые в JavaScript 1 ¦ 1 и следующих версиях. Свойство Объект Свойство Объект applets arguments border caller closed complete constructor current Document Function Image Function Window Image Object History defaultSelectedl description domain embeds enabledPlugin filename formName forms hash height history host hostname href hspace images Java length lowsrc MAXVALUE mimeTypes MINJ/ALUE NaN NEGATIVEJNFINITY name netscape next opener pathname plugins |port POSITIVEJNFINITY previous protocol prototype search src suffixes sun target type vspace width Option MimeType, Plugin Document Document: MimeType Plugin Document Document Area Image Window Area Area Area Image Document Packages Array, Plugin Image Number1 Navigator Number Number Number Image, Plugin Packages History Window Area Document, Navigator Area Number History Area Boolean, Function, Image, Number, Object Area Image MimeType Packages Area Button, Checkbox, FileUpload, Hidden, MimeType, Password, Radio, Reset, Select, Submit, Text, Textarea Image Image
Избранные программные технологии Часть V Таблица 26.6. Методы, поддерживаемые в JavaScript 1.1 и следующих версиях. Метод Объект blur Button, Checkbox, FileUpload, Frame, Submit, Window click eva! focus javaEnabled join refresh reload replace reset reverse scroll sort split taintEnabled toSource toString valueOf Checkbox Object Button, FileUpload, Frame, Submit, Window Navigator Array Plugins Location Location Form, Reset Array Window Array String Navigator Array, Boolean Array, Boolean, Number, Object Object Таблица 26.7. Обработчики событий, поддержива- поддерживаемые в JavaScript 1.1 и следующих версиях. Обработчик Объект событий onAbort Window, Image onBlur Button, Checkbox, FileUpload, Frame, Submit, Window FileUpload Checkbox Window, Image Button, Checkbox, FileUpload, Frame, Submit, onChange onClick onError onFocus Window on Load Image onMouseOut Area, Link onMouseOver Area onReset Form JavaScript 1.2 JavaScript 1.2 поддерживается в Netscape Navigator 4.0- 4.05. Приведенные ниже списки перечисляют расшире- расширения объектов, операторов и возможностей, которые были добавлены в JavaScript 1.2 и в предыдущих вер- версиях не поддерживаются. Объекты Anchor Event Layer Операторы export import Возможности RegExp Screen labeled switch ¦• Добавлена возможность управления слоями. Добавлена возможность программного управления таблицами стилей. • В метод ореп() окна добавленыдополнительные па- параметры, позволяющие осуществлять дополнитель- дополнительную настройку открываемого окна. • Если параметр LANGUAGE дескриптора <script> ра- равен JavaScriptl.2, операции равенства (== и !=) сравнивают только операнды только подобных ти- типов. Таблицы с 26.8 по 26.10 содержат расширения свойств, методов и обработчиков событий, добавленные в JavaScript 1.2. Таблица 26.8. Свойства, поддерживаемые в JavaScript 1.2 и следующих версиях. Свойство Объект above anchors arity background below bgColor data document height innerHeight innerWidth language layers layerX layerY left locationBar menuBar modifiers .name outerHeight outerWidth Layer Document Function Layer Layer Layer Event Layer Document, Event Window Window Navigator Document Event Event Layer Window Window Event Anchor, Layer Window Window
Гарантия работы сценариев е браузерах Netscape и Microsoft Свойство радеХ pageXOffset pageY pageYOffset parentLayer personalbar platform scree nX screenY scrollbars siblingAbove siblingEelow src statusbar target text top toolbar type visibility which width X У zlndex Кроме того, Объект Event, Layer Window Event, Layer " Window Layer Window Navigator Event Event Window Layer Layer Layer Window Event Anchor, Link Layer Window Event Layer Event Document, Event Anchor Anchor Layer поддерживаются все свойства, связан- ные с объектами RegExp и Screen. Таблица 26.9. JavaScript 1.2 Метод Back CaptureEvents Clearlnterval ClearTimeout compile concat Методы, поддерживаемые в и следующих версиях. Объект Window Document, Layer, Window Frame, Window Frame RegExp Array, String disableExternalCapture Window enable ExtemalCapture Windwow exec find forward getFullYear getMilliseconds getSeiection RegExp Window Window Date .Date Document Метод getUTCDate getUTCDay getUTCFullYear getUTCHours getUTCMilliseconds getUTCMinutes getUTCMonth getUTCSeconds handleEvent home load match move Above imoveBelow move By moveTo moveToAbsolute pop print push releaseEvents replace resizeBy resizeTo irouteEvents scroll By scrollTo search setFullYear setinterval setMilliseconds setUTCDate setUTCFullYear setUTCHours setUTCMilliseconds setUTCMinutes setUTCMonth setUTCSeconds setinterval shift slice splice stop substr Глава 26 Bill Объект Date Date Date Date Date Date Date Date Area, Button, Checkbox, Document, Form, Image, Layer, Link, Password, Radio, Reset, Select, Submit, Text, Textarea, Window Window Layer String Layer Layer Layer, Window Layer, Window Layer Array Frame, Window Array Document, Layer, Window String Layer, Window Layer, Window Document, Layer, Window Window Window String Date Window Date Date Date Date Date Date Date Date Frame Array Array, String Array Window String
Избранные программные технологии Часть V Метод Объект test toSource tollTCString unshift unwatch watch RegExp Array Date Array Object Object Таблица 26.10. Обработчики событий, поддержи- поддерживаемые в JavaScript 1.2 и следующих версиях. Обработчик событии Объект onBlur onDblClick onDragDrop onFocus onKeyDown onKeyPress onKeyUp onLoad onMouseDown onMouseOut onMouseOver onMove onResize Layer Unk Window Layer llmage, Link, Textarea Image, Link, Textarea llmage, Link, Textarea Layer Unk Layer Layer Frame, Window Frame, Window JavaScript 1.3 JavaScript 1.3 поддерживается в Netscape Navigator 4.06- 4.7x. Ниже приведены списки расширения функций и возможностей, добавленные в JavaScript 1.3 и не под- поддерживаемые в предыдущих версиях. Функции IsFinite isNaN Возможности Соответствие ECMAScript 1.A Поддержка Unicode. Новые операции строгого равенства ===== и !==. Изменения в операциях равенства == и ! =. Запрещение применения простого присваивания в условном операторе типа if (x = у). Любой объект с определенным и ненулевым значе- значением (включая объект логического типа, равный false) при передаче его в условный оператор счита- считается равным true. Таблица 26.11 содержит список расширений мето- методов, добавленных в JavaScript 1.3. Таблица 26.11. Методы, поддерживаемые в JavaScript 1.3 и следующих версиях. _ Метод Объект apply Function call Function toSource Array, Date, Function, Number, Object, String toString String JavaScript 1,4 Компания Netscape не выпускала новых версий брау- браузера до тех пор, пока не появился JavaScript 1.4. Новые функциональные возможности версии 1.4 перешли в JavaScript 1.5 и поддерживаются в Netscape Navigator 6.0. Ниже приведены списки расширений операций и операторов, добавленных в JavaScript 1.4 и не поддер- поддерживаемых в предыдущих версиях. Операции in instanceof Операторы catch throw try JavaScript 1.5 JavaScript 1.5 — последняя реализация Netscape, кото- которая поддерживается в Netscape Navigator 6.0. Ниже при- приводится список расширений возможностей, добавлен- добавленных в JavaScript 1.5 и не поддерживаемых в предыдущих версиях. Возможности Согласование с ECMAScript 3.0. Ошибки времени выполнения программы проявля- проявляются через исключения. Расширения регулярных выражений. Таблица 26.12 содержит список расширений мето- методов, добавленных в JavaScript 1.5. Таблица 26.12. Методы, поддерживаемые в JavaScript 1.5. Метод Объект toFixed toExponential Number Number JScript от Microsoft Этот раздел включает три подраздела, по одному на версию JScript. В каждом подразделе подробно рассмат-
Гарантия работы сценариев в браузерах Netscape и Microsoft Глава 26 риваются все объекты, свойства, методы, обработчики событий, встроенные функции, операции и операторы, новые для конфетной версии JScript. 1 СОВЕТ 5 Для получения актуальной информации о новых версиях JScripi посетите Web-сайт Microsoft по адресу http:// msdn.microsoft.com/scripting/JScript/default.hfm. JScript 1.0 JScript 1.0 поддерживается в Microsoft .3.0. Ниже приведены списки основных кций, операций Объекты Area Button Checkbox Date Document Embed FileUpLoad Form Frame Функции escape eval parseFloat Операции - &= - + 4 += ¦ —= > : Операторы For for. ..in function if...else и операторов. Function Hidden History Link Location Math Navigator Option Password parse tnt unescape ! != % %= ¦= , / /**/ Л— ¦ 1 1 ~ 1 1 1 = < << <<= < = >= >> >>= >>> return while with Internet Explorer объектов, фун- Radio Reset Select String Submit Text Textarea Window & & & // /= r »>= new Таблицы с 26.13 по 26.15 перечисляют основные свойсгва, методы и обработчики событий. Таблица 26.13. Свойства, поддерживаемые в JScript 1.0 и следующих версиях. Свойство Объект action aLinkColor appCodeName applet:; appName Form Document Navigator Document Navigator Свойство Объект appVersion .Navigator bgColor Document checked Radio cookie Document defaultChecked Radio defaultStatus Window defaultValue Password, Text, Textarea document Frame, Window E Math elements, Form encoding i Form fgColor Document form Button, FileUpload, Hidden, Password, Radio.Reset, Select, Submit, Text, Textarea form Reset, Select, Submit frames Frame, Window hash Area, Link, Location host Area, Link, Location hostname Area, Link, Location href Area, Link Location llastModified Document length Form, Frame, History, Select, String linkColor Document Ilinks Document LN10 'Math iLN2 Math location Document, Window 'LOG10E Math L0G2E iMath method Form name Button, FileUpload, Form, Frame, Hidden,Password, Radio, Reset, Select, Submit, Text.Textarea, Window options Select parent 'Frame, Window pathname Area, Link, Location PI Math port Area, Link, Location protocol! Area, Link, Location previous History referrer Document search Area, Link, Location selected Option selectedlndex Select self .Frame, Window
¦¦¦¦ Избранные программные технологии В?Ш| Часть V Свойство SQRT1_2 SQRT2 status target Г' <t title top type userAgent URL vlinkColor value> window Таблица 26 JScript 1,0 Метод abs acos alert anchor asin atari atan2 back big blink bold blur ceil charAt charCodeAt clear Timeout click close confirm cos ¦¦!P fixed floor focus fontcolor1 Объект IMath Math Window Area, Form, Link Option Document Frame, Window Button iNavigator Document Document Button, FileUpload, Hidden, Option, Password, Radio, Reset, Submit, Text, Textarea Frame .14. Методы, поддерживаемые в и следующих версиях. Объект Math Math. Window String Math Math Math History String String String Button, Checkbox, Password, Radio, Reset, Select, Text, Textarea Math String String Window Button, Radio, Reset, Submit Document, Window Window Math Math String Math Button, Password, Radio, Reset, Select, Text, Textarea String Метод fontSize forward fromCharCode ¦getDate getDay getHours getMinutes getMonth getSeconds getTime getTimezoneOffset getYear go indexOf italics lastlndexOf link. Imj «пах min open parse pr.r prompt random. round select setDate setHours setMinutes. setMonth setSeconds setTime setTimeout setYear sin sqrt strike s;ub submit substring sup '; in toGMTString toLocaleString toLowerCase Объект String History String Date Date Date Date Date Date Date Date Date History String String String String IVyiath IVIdU 1 Math Math Document, Window Date Math Window Math Math FileUpLoad, Passwor Date Date Date Date Date Date Frame, Window Date Math Math String String Form String String Math Date Date ¦String
Гарантия работы сценариев в браузерах Netscape и Microsoft Метод JoSource toString toUpperCase UTC write writeln Объект Math Date, Math String Date Document Document Таблица 26.15. Обработчики событий, поддержи- поддерживаемые в JScript Обработчик событий on Blur onChange onClick onDblClick onFocus onKeyDown onKeyPress onKeyUp onLoad onUnLciad onMouseDown onMouseOver onMouseUp onSelect onSubmit JScript 3.0 1 .0 и следующих версиях. Объект Password, Radio, Reset, Select, Text, Textarea Select, Text, Textarea Button, Document, Radio, Reset, Submit, Text Document Password, Radio, Reset, Select, Text, Textarea Document Document Document Window Window Button, Document Link Button, Document Textarea Form JScript 3.0 поддерживается в Microsoft Internet Explorer 4.0-4.5. Ниже приводятся списки расширений объектов, операций и операторов, добавленных в JScript 3.0 и не поддерживаемых е Объекты Applet Array Boolean Event Image MimeType Операции typeof Операторы continue delete i предыдущих версиях. Number Object Plugin RegExp Screen void do...while import switch export labeled Таблицы с Глава 26 ШШЯ 26.16 по 26.18 содержат свойства, мето- ды и обработчики событий, добавленные в JScript 3.0. Table 26.16. ( Овойства, поддерживаемые в JScript 3.0 и следующих версиях. Свойства $* $& $_ $¦ $¦ $+ $1,$2,[е1]$9 all anchors arguments arity availHeight availWidth border caller checked closed colorDepth complete constructor current data defaultChecked defaultSelected description domain embeds enabledPlugin filename form formName forms global height history hspace ignoreCase images innerHeight innerWidth input language Объект RegExp RegExp RegExp RegExp RegExp RegExp RegExp Document Document Function Function Screen Screen Image Function Checkbox Window Screen Image Object Historv 1 II \J LVy 1 у Event Checkbox Option MimeType, Plugin Document Document MimeType Plugin Checkbox Document Document RegExp Event, Image, Screen Window Image RegExp Document Window Window RegExp Navigator
Избранные программные технологии Часть V выбрать способ обхода ошибок с помощью методики выяснения типа браузера, описанной в главе 27, или вообще не использовать в сценарии спорные методы решения. Поскольку ошибки браузера существенно отличают- отличаются в зависимости от версий браузеров, каждая из них в отдельности рассматриваться не будет. При создании сценария лучше всего в первую очередь учитывать ошибки именно тех браузеров, которые будут поддер- поддерживать данный сценарий. Как только принято решение о типах браузеров, стоит потратить некоторое время на обзор ошибок, связанных с этими браузерами. Потру- Потрудитесь убедиться, что ошибки браузеров не мешают сце- сценариям. Компания Netscape проделала громадную работу по обеспечению доступа к полному списку всех ошибок, имеющих отношение к JavaScript и связанных с брау- браузерами Netscape. Этот список ошибок находится на их сайте по адресу http://devedge.netscape.com/support/ bugs/known/ JavaScript.html. Microsoft, напротив, не поддерживает доступный список связанных с JScript ошибок, следовательно, по- понадобится потратить какое-то время на поиск описания ошибок на сайте Microsoft (msdn.microsoft.com). Резюме В главе рассматривались реализация JavaScript в брау- браузерах Microsoft и Netscape. На заре своего появления язык JavaScript создавал программистам множество про- проблем, но сейчас, наконец-то, стабилизировался — бла- благодаря усилиям Netscape, Microsoft и ЕСМА. Однако, несмотря на стабильность JavaScript, не все могут ис- использовать самые новые браузеры. По этой причине важ- важно знать, какие функциональные возможности JavaScript поддерживаются в различных версиях браузеров, а так- также принимать во внимание, что каждый браузер имеет свой набор досадных ошибок. Информация из этой гла- главы поможет обеспечить качественную работу сценари- сценариев в браузерах Microsoft и Netscape.
Методы выяснения типа браузера В ЭТОЙ ГЛАВЕ Подход "Все или ничего" Подход "Выяснение по месту" Перед описанием темы главы автору хотелось бы представить читателям Джо. Джо — Web-разработчик, который имеет огромное желание оживить собственный Web-сайт, создав с помощью JavaScript специальные эффекты, упрощенную навигацию по сайту, анимиро- ванньге кнопки и возможности верификации данных. Потратив немалую энергию и сделав все задуманное, Джо вспомнил, что следовало бы убедиться в том, что все разработанное под Netscape Navigator будет работать и в Microsoft Internet Explorer, а также в старых верси- версиях Netscape Navigator. Да, жизнь не удалась. Специаль- Специальные эффекты опирались на неуниверсальные объекты Layer, а в коде было задействовано много объектов Array, которые вызывают проблемы в Navigator 2.O. В результате получилось, что сайт оказался пригодным только тем, кто располагал той же версией браузера, что и у Джо. Хотя Джо — вымышленный персонаж, та же груст- грустная история часто повторяется при реальной разработ- разработке сайтов. Если разработчик использует JavaScript-код, он несомненно столкнется с подобными проблемами. Учитывая различные степени совместимости JavaScript- диалектов, несовместимость — первое, о чем необходи- необходимо помнить в процессе разработки сценария. В конце концов, главная цель использования JavaScript заключа- заключается в расширении возможностей Web-сайта. Если про- проигнорировать проблемы совместимости, то пользовате- пользователи, применяющие браузеры, которые не поддерживают вашу версию JavaScript, будут весьма разочарованы. Поэтому первой целью у разработчика Web-страниц должна быть разработка "надежного" сценария — сце- сценария, максимизирующего возможности более поздних версий JavaScript, но при этом учитывающего возмож- возможности браузеров, обеспечивающих меньшую степень поддержки. В этой главе рассматриваются два метода выяснения типа браузера клиента. Подход "Все или ничего" Первая методика, которую можно обозначить как под- подход "Все или ничего", определяет, может ли выполнить- выполниться сценарий целиком или он полностью игнорируется браузером. Для применения такой методики в параметре language дескриптора <script> потребуется определить ожидаемый диалект. Операторы в пределах дескрипто- дескриптора <script> будут игнорироваться, если браузер не под- поддерживает заданную версию JavaScript. Преимущество использования данной технологии состоит в том, что можно быть уверенным — если бра- браузер понимает параметр language, то он обеспечит полную1 поддержку требуемого JavaScript-диалекта. Недостаток технологии связан с тем, что браузеры, не поддержива- поддерживающие указанный диалект, принудительно игнорируют весьсценарий. Подход "Выяснение по месту" Альтернативой подхода "Все или ничего" является ме- метод "Выяснение по месту" (иногда называемый "обна- "обнаружение браузера"). Эта технология предполагает опре- определение версии браузера в сценарии перед выполнением кода, критичного к версии JavaScript. Хотя эта методика несколько сложнее, однако она обладает преимуществом в том, что здесь возможно обес- обеспечить альтернативную функциональность для браузе- браузеров, не поддерживающих конкретную версию JavaScript. При помощи объекта Navigator в JavaScript можно по- получить четыре вида полезной информации, связанной с браузером.
Избранные программные технологии Часть V Тип браузера Свойство appName объекта Navigator предоставляет имя браузера клиента. Двумя наиболее популярными брау- браузерами по праву считаются Netscape и Microsoft Internet Explorer. Следующая строка отображает имя браузера: document.write(navigator.appName); Если требуется идентифицировать другие типы бра- браузеров, необходимо использовать свойство userAgent объекта Navigator. Это свойство содержит большой объем информации, но если организовать поиск опре- определенной строки через метод indexOf(), можно иденти- идентифицировать имя браузера. Поскольку значением явля- является строка, неплохо ее преобразовать к нижнему регистру с целью упрощения сравнения. Таблица 27.1 содержит некоторые из наиболее частых значений свой- свойства userAgent и соответствующие им типы браузеров. Таблица 27.1. Значения свойства userAgent. Значение mozilla msie opera webtv Браузер Netscape Navigator Microsoft Internet Explorer Opera WebTV Следующий фрагмент кода определяет различные типы браузера с использованием свойства userAgent: var browserType = navigator.userAgent.toLowerCase(); If (browserType.indexOf('mozilla1) document.write("Netscape Navigator"); else if (browserType.indexOf('msie') document.write("Microsoft Internet Explorer"); else if (browserType.indexOf('opera') document.write("Opera"); else if (browserType.indexOf('webtv') document.write("WebTV"); Г.<ЭД " ';L',. ; «. ^^ ^ .*3^1: Для получения дополнительной информации о строке userAgent посетите Web-сайт по адресу http:// www.it97.de / JavaScript / JS_tutorial / bstat/navobj.html. Версия браузера Свойство appVersion объекта Navigator предоставляет сценарию информацию о версии клиентского браузера. Следующая строка программы отображает версию бра- браузера на экране: document.write(navigator.appVersion); Если преобразовать это свойство в число с плаваю- плавающей точкой (т.е. не целое) с помощью метода parseFloat(), все можно свести к простым математическим сравнени- сравнениям. Почему это удобнее, будет показано в следующем разделе при определении версии JavaScript. Следующая строка кода содержит способ создания такого значения с плавающей точкой: var browserVersion = parseFloat(navigator.appVersion); Версия JavaScript Версия JavaScript 1 0 :0 11 1 2 1.2 1 3 1.4 14 Браузер iNavigator Internet Explorer Navigator Navigator Internet Explorer iNavigator Navigator ilnternet Explorer Воспользовавшись знаниями о JavaScript-диалектах, полученными из главы 26, можно определить, какая вер- версия JavaScript используется по типу браузера и инфор- информации о версии, упоминавшейся выше. Таблица 27.2 показывает, как тип браузера и информация о версии соответствует версии JavaScript. Таблица 27.2. Версии JavaScript. Версия браузера ¦2Q 3.0 3.0 4.0-4.05 4.0 4.06-4.5 5.0 5.0 Платформа операционной системы Свойство platform объекта Navigator представляет ин- информацию о платформе операционной системы клиен- клиента. Следующая строка программы отображает платфор- платформу операционной системы: document.write(navigator.platform); Эта информация будет необходима, если, например, предпринимается попытка обойти в Macintosh ошибку, которая существует только в Netscape Navigator. В боль- большинстве случаев эта информация не нужна, но если все- таки она потребуется, то вам уже известно, как ее по- получить. Пример динамического позиционирования Теперь, когда рассмотрено множество способов получе- получения информации о клиентском браузере и его операци- операционной системе, рассмотрим соответствующий пример. Одно из самых больших и досадных различий меж- между Navigator и Internet Explorer на сегодняшний день — это способы динамического позиционирования. Netscape выполняетдинамическое позиционирование, используя
Методы выяснения типа браузера свой объект Layer, a Microsoft — используя HTML-дес- HTML-дескриптор <div>. Для реализации динамического позици- позиционирования, которое будет работать одинаково хорошо в браузерах как Netscape, так и Microsoft, потребуется записать код на JavaScript для определения типа кли- клиентского браузера. Листинг 27.1 создает два слоя (один красный и дру- другой обычный текст), используя в одном случае дескрип- дескрипторы <div>, в другом —дескрипторы <1ауег>. Красный блок содержит кнопки, которые перемещают блок вдоль окна браузера. Красный блок также имеет кнопку, ко- которая заставляет текстовое поле исчезать и вновь появ- появляться (см. рис. 27.1). Фактическое движение выполня- выполняется путем изменения значений свойств слоя в случае слоев в Netscape или через таблицу стилей в случае бло- блока <div>. Дополнительную информацию об использо- использовании слоев и дескриптора <div> можно найти в главе 23. Листинг 27.1. Обнаружение браузеров Navigator и! Internet Explorer. <html> <body> <script language="JavaScript"> //Создать дескриптор <1ауег>, если это netscape if(navigator.appName.indexOf("Netscape") != -1) document.write('<layer id="redBox" ') ; //Создать дескриптор <div>, если это Microsoft if(navigator.appName.indexOf("Microsoft") != -1) document.write("<div id='redBox1 ") ; //Установить стиль, используемый красным блоком document.write('style="position:absolute; ') ; document.write('left:150px; ') ; document.write('top:150px; '); document.write('background-color:red;">'); </script> This is <form> '<inpu t: <input <inpu1: <inpul: </form> a block of moving buttons type="button" value="UP" onClick="moveOp()"> type="button" value="DOWN" onCLick="moveDown О "> type="button" value="LEFT" onClick="moveLeft()"> type="button" value="RIGHT" onClick="moveRight(> "XBR> type="button" value=" SHOW/HIDE Text Box" onClick="showHide()"> <script language="JavaScript"> Глава 27 //Если это Netscape, выдать закрывающийся //дескриптор </layer> if {navigator.appName.indexOf ("Netscape") != -1) document. write ( "</layer>") ; У/Если это Microsoft, выдать закрывающийся //дескриптор </div> if (navigator.appName.indexOf ("Microsoft") != -1) document.write("</div>"); II—> ¦</script> <script language="JavaScript"> //Если это Netscape, создать текстовый блок //через <layer> if (navigator.appName. indexOf ("Netscape") != -1) ¦! document.write ( '<layer id="textBox" >'); document .write ("Here is some text defined as a block") ,- document.write("</layer>"); //Если это Microsoft, создать текстовый блок //через <div> if (navigator.appName.indexOf ("Microsoft") != -1) ( document.write ("</div>"); document.write("<divid=¦textBox'>") ; document, write ("Here is some text defined as '^a block") ; document.write ( "</div>1> ; 1 II—> </script> <script language="JavaScript"> var isNetscape = 0 ; var isMicrosoft = 0; //Определение типа браузера if (navigator. appName. indexOf ("Netscape") != -1) isNetscape = 1 ; if (navigator,appName.indexOf ("Microsoft") != -1) isMicrosoft = 1 ; //Переместить красный блок на 20 пикселов вверх function move Op ( ) i if (isNetscape) document, layers. redBox.pageY+=( -20) ; if(isMicrosoft) document, all. redBox .style .pixelTop+= ( -20) ; ) //Переместить красный блок на 20 пикселов вниз function moveDown ( ) Ч if(isNetscape) document. layers. redBox.pageY+=20; if (isMicrosoft) document. all. redBox. style. pixelTop+=20 J //Переместить красный блок на 20 пикселов влево function moveLeft() ¦i if(isNetscape)
Избранные программные технологии Часть V document.layers.redBox.pageX+=(-20); if(isMicrosoft) document.all.redBox.style.pixelLeft+=(-20) ; стить красный блок на 20 пикселов //вправо function moveRight() if (isNetscape) document.layers.redBox.pageX+=2 0; if(isMicrosoft) document.all.redBox.style.pixelLeft+=20; } //Скрыть или отобразить текстовый блох function showRide() if(isNetscape) //Если текстовый блок скрыт, сделать его //видимым if(document.layers.textBox.visibility == "hide") document.layers.textBox.visibility="inherit"; else document.layers.textBox.visibility="hide"; 1 if(isMicrosoft> ¦I //Если текстовый блок скрыт, сделать его //видимым if(document.all.textBox.style.visibility == "hidden") document.all.textBox.style.visibility^1 visible"; else document.all.textBox.style.visibility="hidden"; </script> </body> </html> . ПРВДУПРЕЖДЕНИЕ В Netscape Navigator, как вы, вероятно, обратили вни- внимание, при перемещении кнопок текст, связанный с кнопками, иногда двигается в беспорядке. Это проис- происходит из-за того, что при изменении свойства layer Netscape не обновляет весь экран. Internet Explorer в данном случае работает лучше, поскольку он обнов- обновляет экран при изменении свойств таблицы стилей. Кро- Кроме того, Netscape случайным образом перекрашива- перекрашивает фон слоя в красный цвет. В последнем примере метод indexOf() применялся для поиска строки "Netscape" или "Microsoft" в свойстве appName объекта Navigator. В зависимости от того, ка- какая строка найдена, значение true присваивается либо переменной isNetscape, либо переменная isMicrosoft. Эти переменные затем используются для определения, какие именно функциональные возможности браузера должны применятся. Если в сценарии требуется более детальная инфор- информация о браузере, полезно создать функцию, которая определяет и тип браузера, и его версию. Например, фун- функция determineCurrentBrowser(). показанная в следующем коде, исследует свойства appName и appVersion объекта Navigator и затем на их основе устанавливает значение глобальной переменной CURRENT_BROWSER: /* Глобальные переменные */ var CORRENT_BROWSER = new String () ; РИСУНОК 27.1. Обнаружение браузеров Navigatoru Internet Explorer. I* determineCurrentBrowser() { var bwr = navigator. appName ; var ver = parseFloat(navigator.appVex if ( bwr = "Netscape" fifi ver >= 5) CURRENT_BROWSER = "Netscape ! .if ( bwr = "Netscape" fifi ver >= 4.06 && ver <=4.5) CURRENT_BROWSER = "Netscape «4.06 - 4.5",- if ( bwr = "Netscape" && ver >= 4 ss ver <= 4.05) C0RRENT_BROWSER = "Netscape >.0 - 4.05"; if ( bwr == "Netscape" && ver = 3 ) CURRENT_BROWSER = "Netscape 3.0" if ( bwr = "Netscape" Si ver = 2 ) CURRENT_BROWSER = "Netscape 2.0"; В качестве альтернативы, можно забыть о браузерах и сосредоточиться на самых высокоуровневых возмож- ностях предлагаемой версии JavaScript. Преимущество такого метода состоит в том, что зачастую он оказыва- оказывается проще применительно для операций сравнения: /* Глобальные переменные var JS VERSION
Методы выяснения типа браузера Глава 27 function JSVersionCheok() { var bwr = navigator.appName; var ver = parseFloat(navigator.appVersion); if ( bwr = "Netscape" && ver >= 5) JS_VERSION = 1.4; if (~bwr = "Netscape" ?? ver >= 4.06 S& ver <=4.5) JS_VERSION = 1.3; if ( bwr = "Netscape" SS ver >= 4 SS ver <= 4.05) JS_VERSION = 1.2; if ( bwr == "Netscape" && ver = 3 ) JS_VERSION = 1.1,- if ( bwr = "Netscape" && ver = 2 )¦ JS VERSION = 1.0; Резюме В главе были рассматривались два метода, которые мож- можно использовать для преодоления несовместимости в сценариях. Первичная цель применения JavaScript со- состоит в расширении возможностей Web-сайтов. Если проигнорировать проблемы совместимости, то пользо- пользователи, применяющие браузеры, которые не поддержи- поддерживают выбранную разновидность JavaScript, не смогут получить то, что ожидали. Таким образом, при создании сценариев необходимо задействовать методы выяснения типа браузера, которые расширяют возможность приме- применения более поздних версий JavaScript, но при этом так- также учитывают браузеры, обеспечивающие меньшую сте- степень поддержки.
Навигация по сайту с использованием JavaScript В ЭТОЙ ГЛАВЕ Исследование технологий навигации Создание сценария для динамической инструментальной панели Использование объекта History Исследование технологий навигации JavaScript перекладывает большую часть работы по дос- доставке и форматированию содержимого на браузер вмес- вместо реализации этих операций на стороне сервера. Одной из положительных черт подобного управления со сторо- стороны клиента является усовершенствование навигации. Вместо обеспечения простых статических ссылок, свя- связывающих Web-страницы сайта, разработчики могут теперь задействовать JavaScript для управления отобра- отображением информации на сайте. До появления фреймов было трудно добавлять на- навигационные средства к Web-странице без того, чтобы ограничить по нескольким направлениям схему разме- размещения информации на сайте и его содержимое. Напри- Например, отображение карты, постоянно показывающей вид сайта, можно было реализовать только за счет помеще- помещения ее на каждую страницу. Карта должна была иметь достаточно небольшие размеры, дабы не отвлекать пользователя. Если просматриваемая страница была слишком длиной, карта во время просмотра страницы пользователем часто оказывалась недоступной. Ограни- Ограничение сайта до одной страницы не могло, конечно же, рассматриваться в качестве варианта, а если карта сайта была доступна только на протяжении части времени про- просмотра, это выглядело весьма непрофессионально. Фреймы помогают решить эту проблему. Разбиение окна браузера на подокна позволяет сохранять карту сайта видимой все время, пока пользователь просматри- просматривает разные страницы HTML-документа. За счет щелч- щелчков на ссылках, находящихся на карте сайта, новая стра- страница отображается в другом фрейме. JavaScript для этого не требуется. Просто используйте атрибут target деск- дескриптора <А> для указания на любой требуемый фрейм. Однако, возникает вопрос — что делать, если текущая страница содержит форму ввода данных, которая долж- должна быть отправлена перед переходом к другой страни- странице? Отправка формы с помощью кнопки "Submit" — это хорошо, но она переведет пользователя на новую стра- страницу, не содержащую карту. В ряде случаев лучшим выходом может оказаться предоставление пользователю возможности перемещения по всему сайту без необхо- необходимости нажатия на кнопку отправки формы после ее заполнения. Это достигается с помощью JavaScript, если только поместить формы в фреймы. В случае, если карта сайта достаточно велика, в каж- каждый момент времени можно отображать только часть карты. При этом возникает необходимость в обновле- обновлении карты. Как обновить карту, отправить форму, ото- отобразить полный документ и проследить местонахожде- местонахождение пользователя с помощью одного щелчка мыши? Самый простой путь для этого — JavaScript. Описан- Описанные в главе навигационные методы демонстрируют способы создания и использования динамической ин- инструментальной панели, а также использование JavaScript- объекта History. Создание сценария для динамической инструментальной панели Инструментальная панель один из элементов стандарт- стандартного пользовательского интерфейса, часто используемо- используемого для навигации практически в любом приложении. В JavaScript динамическая инструментальная панель — это панель, которая изменяется в результате взаимодействия пользователя с ней. Для примера ниже показана инст- инструментальную панель, которая управляет простой слай- слайдовой демонстрацией. Четыре кнопки на инструменталь-
Навигация по сайту с использованием JavaScript ной панели используются для перемещения вперед и назад по массиву слайдов. Две других кнопки исполь- используются для запуска или останова автоматического цик- цикла по всем слайдам. Логический путь создания такой программы состоит в построении двух объектов — Button и Toolbar. Создание объекта Toolbar Инструментальную панель можно рассматривать как набор кнопок, поэтому дадим объекту Toolbar имя buttonSet. Листинг 28.1 показывает конструктор buttonSet, который обычно устанавливает все свойства и методы, доступные в инструментальной панели. Листинг 28.1. Конструктор объекта buttonSet. function buttonSet(name) * Описание: конструктор объекта кнопки. * Аргументы: name - Имя переменной buttonSet. // Свойства this.name = name; this.startlndex =  ; this.length = 7; this.isBusy = false; // Метода this.addBtn = addBtn; this, print = print; this.clear = clear; return this ; 1 Метод addBtn создает и добавляет в buttonSet новый объект Button. Метод print записывает buttonSet в HTML- документ. Метод clear устанавливает все кнопки, содер- содержащиеся в пределах buttonSet, в их первоначальное со- состояние доступности/недоступности. Эти методы подробно описываются в следующих разделах. Использование объекта Button Объект buttonSet используется для управления одним и более объектов Button. Каждый объект Button содержит информацию о нажатии кнопки или отображении ее в виде HTML-элемента <lmg>. Листинг 28.2 показывает две функции, которые применяются для создания но- нового объекта Button. Листинг 28.2. Метод click и конструктор объекта Button. function click() f Глава 28 * Аргументы: Нет. */ eval(this.command) ; I function button (name, file, alt, url, spacer, condition, command) * Описание: объект кнопки. * Аргументы: * name - Имя кнопки в HTML-коде. * file - URL изображения кнопки. * alt - Атрибут alt для кнопки. * url - URL соответствующего buttonSet. * spacer - количество пикселов после кнопки. * condition - условный оператор, который * определяет, должна ли * отображаться эта кнопка. * commmand - Команда, которую реализуем * кнопка. // Свойства this, name = name; this.file = file; this.alt = alt; this.url = url; this.spacer = spacer; this. condition = condition; this.command = command; // Методы this.click = return this ; click; /* * Описание: Метод объекта кнопки. Реализует * команду этой кнопки. Свойство name представляет HTML-имя кнопки. Свойство file кнопки — исходный URL-адрес изображе- изображения кнопки. Свойство alt хранит значение HTML-атри- HTML-атрибута alt. Свойство U RL применяется в качестве свойства HREF якоря, связанного с изображением кнопки. Ис- Используя графический файл с прозрачностью, свойство spacer определяет, сколько места осталось для размеще- размещения изображения еще одной кнопки справа от данной. Это позволяет создавать в инструментальной панели различные разделы либо помещать туда изображения кнопок разной величины. Button будет отображаться только, если его условное выражение равно true. Это — ключ к определению того, какие кнопки отображены и доступны для нажатия. Всякий раз когда объект buttonSet присутствует на HTML-странице, необходи- необходимо смотреть на условное выражение для каждого объек- объекта Button, чтобы определить, доступен ли Button для щелчка. Если доступен и пользователь щелкает на кноп- кнопке, команда выполняется. Строка команды может быть любым оператором JavaScript в случае, если она выпол- выполняется в контексте документа, в котором был создан buttonSet.
Избранные программные технологии Часть V Созданиеэкземпляровинструментальной панели С помощью приведенных ниже строк кода программа слайдовой демонстрации создает новый объект buttonSet и сбрасывает его текущее состояние. Toolbar = new buttonSet("Toolbar"); Toolbar.cleax (); При создании нового экземпляра buttonSet важно, чтобы аргумент, переданный конструктору, был равен имени переменной создаваемого объекта. Это позволя- позволяет объекту buttonSet создавать команды JavaScript, ис- используя собственное имя. Метод clear() используется для установки и сброса значений глобальных перемен- переменных, использующих buttonSet для определения, какие из его кнопок разрешены для нажатия. Листинг 28.3 по- показывает метод clear(), реализованный для приложения Slide Show. Листинг 28.3. Метод clear() объекта buttonSet. function clear () /* * Описание: Метод объекта buttonSet. * Используется для сброса всех 1 глобальных переменных, на * поторые ссыпаются пноппи в * buttonSet на основе своих '* УСЛОВНЫХ выражений. * Аргумента!: Нет. */ gIsRunning=false; Как только новый экземпляр buttonSet создан, при- приложение Slide Show с использованием метода addBtn() создает кнопки. Первая создаваемая кнопка показана в следующем коде: Toolbar.addBtn("First","graphics/first.gif", "First Picture",0,"true", "changeSlide (¦first')"); Листинг 28.4 отображает полный код метода addBtn(), который создает новый объект Button и затем добавляет его в buttonSet. Листинг 28.4. Метод addBtnQ объекта buttonSet. function addBtn(name,file,alt,spacer,condition,command) * Описание: Метод об-ькта buttonSet, которьм * добавляет новую кнопку set. * Аргументы: name - (string) Имя кнопки в * HTML-коде. * file - (string) URL изображения * кнопки. * alt - (string) Атрибут alt * кнопки. spacer - (integer) колияество пикселов после кнопки. condition - (string) условный операторf которьм определяет, должна ли отображаться кнопка. commmand - (string) Команда, которую реализует кнопка. var i = this.length; this[i] = new button(name,file,alt, "javascript:parent. "+this.name+" ["+i+']"+ ".clickO ",spacer,condition,command) ; this.length++; Аргумент url, указанный для конструктора кнопки в листинге 28.4, заслуживает дополнительного внимания. Эта строка будет использоваться как свойство HREF изображения кнопки. Приведенный ниже пример — это HTML-код, сгенерированный для первой кнопки Slide Show: <Д href="javascript:parent.Toolbar[7].click)) "> <img src="graphics/first.gif" alt="First Picture" width=4" height=4" border=0> Когда пользователь щелкает на изображении, вызы- вызывается метод click() седьмого свойства объекта Toolbar. Седьмой элемент в объекте Toolbar (который, по суще- существу, является массивом) — это элемент, в котором при помощи метода addBtn() был сохранен первый объект Button. Это — лучший способ вызвать метод click() в любом фрейме, хорошо работающий как в браузере Microsoft, так и в Netscape. Объект buttonSet установ- установлен таким образом, что программист, использующий его, не должен следить за нумерацией кнопок. Отображение инструментальной панели Глобальная переменная glsRunning будет иметь значе- значение true, если программа слайдовой демонстрации ав- автоматически проходит через каждый слайд; иначе она будет равна false. Эта переменная используется в четы- четырех объектах Button для отображения двух кнопок од- одновременно. Одна иллюстрирует активное состояние, а другая — заблокированное (кнопка недоступна для щел- щелчка, что отображается на экране бледными цветами). Следующие примеры содержат две кнопки, которые за- зависят от glsRunning: Toolbar.addBtn("Start", "graphics/auto. gif", "Start Slideshow", 0, "gIsRunning=false", "changeSlideCstart1}") ; Toolbar. addBtn (" StartGrey" , "graphics/ **autoGrey.gif", "Start Slides how", 0, "gIsRunning=true", "");
Навигация по сайту с использованием JavaScript Кнопка StartGrey отображается только, если значе- значение glsRunning равно true. Если же glsRunning равна false, отображается кнопка Start. Если кнопка Start до- доступна и пользователь совершает на ней щелчок, в фун- функции changeSIideO выполняется следующий код: if(command = "start") { glsRunning = true; Toolbar.print(window.frames[2].document); gTimer = window.setTimeout("startAuto()",1500); .) Значение переменной glsRunning установлено в true, а инструментальная панель помещена в выбранный объект Document. Текущая инструментальная панель удаляется и создается новая HTML-страница, содержа- содержащая новую инструментальную панель, которая учиты- учитывает новое состояние glsRunning. Это означает, что кнопка StartGrey будет доступной, а кнопка Start даже не помещена на новую страницу. Это дает иллюзию ус- установки запрета выбора кнопки "Start", тогда как на самом деле это совсем другая кнопка. В листинге 28.5 показан метод print(), который отвечает за подготовку новой HTML-страницы. Метод print() начинается с установки флажка isBusy в true, что предотвращает нажатие пользователем других кнопок во время обновления инструментальной панели. Листинг 28.5. Метод printQ объекта buttonSet. Глава 28 Затем формируется базовый URL, который приравнива- приравнивается к базовому URL текущего окна. Он сохраняется в переменной topBase и используется при генерации дес- дескриптора <base> для нового документа с инструменталь- инструментальной панелью. Предполагается, что имя файла для уста- устанавливающего фреймы HTML-документа и"меет длину двенадцать символов, например, SIideSilw.htm. Это дол- должно обеспечить согласование с версиями до Netscape Navigator 3.0. ^ПРЕДУПРЕЖДЕНИЕ ^ , ', Если ошибиться в определении базового URL для сге- сгенерированного при помощи JavaScript HTML-докумен- HTML-документа, то версии Netscape Navigator до 3.0 не смогут понять некорректный URL. Метод print() продолжает работу, открывая, доступ к целевому документу. Затем метод записывает каждую строку HTML, требуемую для формирования Web-стра- Web-страницы с инструментальной панелью. Для центрирования кнопок можно воспользоваться таблицей. Цикл for при- применяется для последовательной записи каждой кнопки, которая сохраняется в buttonSet. Если был задан сим- символ пробела, напечатается пустой графический символ и "размножится" до требуемого количества пикселов. На- Наконец, документ закрывается и окно браузера обновля- обновляется. function print (dob j) * Описание: Метод об"ьекта buttonSet. * Аргументы: dobj - объект document, содержащий buttonSet. */ this.isBusy = true; var spacelnt; var DQOOTE = 'V"; var topBase = "" ; var basePath = ""+window.location.pathname; var baseDir = ""; var baseFile = basePath.substring(basePath.length-10,basePath.length); baseDir = basePath.substring@,basePath.length-12); topBase=window.location.protocol+"//"+window.location.host+baseDir; dObj .open 0; dObj.bgColor = parent.frames[0].document.bgColor; dObj.writeln('<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">'); dOb j . writeln (' <htmlxhead>') ,• dObj.writeln('<title>Toolbar</title>'); dObj.writeln('<base href = ¦ +DQOOTE+topBase+DQtJOTE+' >') ; dObj.writeln('<script language="JavaScript">'); dObj.writeln('</script>'); dObj.writeln('</head>') ; dObj.writeln('<body bgcolor="'+ parent.frames[0].document.bgColor.toUpperCase()+' dObj.writeln('<center>'); dObj.writeln('<table width=00%" border=">'); dObj .writeln ('<trxtd align="center">') ; //Вывод кнопок, начиная со свойства с номером i.
Избранные программные технологии Часть V for(var i = this.startlndex; this.length > i; i++) ( if(eval(this?i].condition)> II dObj .write ("<A HREF = " 4-this[i] .url+'">') ; dObj.write('<img src=" '+this[i] .file+'" alt=" '+tiia[i].alt+'" width=4" height=4" *»border=0>' ) ; dObj .write( ' </A>" ) ; // Добавить пустое пространство, если это определено. spacelnt = 0 + this[i] .spacer; if(spacelnt != 0) t dObj .write ( '<imgsrc="graphics/space.gif" width= '+spacelnt+' height= 24 border=0>') ; I dObj .writeln( •</tdx/trX/table>1) ; dObj.writeln('</center>'); dObj .writeln< 1</bodyX/html>!) ; dObj . close (У ; this.isBusy = false; Обновление инструментальной панели Как можно понять из сказанного выше, обновления инструментальной панели проводить легко, необходимо только вызвать метод print(). Просто установите глобаль- глобальные переменные, от которых зависят кнопки, и вызовите prmt(). Документы в других фреймах могут также обнов- обновлять инструментальную панель. Например, несложно изменить приложение Slide Show так, чтобы пользова- пользователь не смог запустить слайдовую демонстрацию, начи- начиная с последнего слайда. Для этого потребуется добавить в метод clearO новую глобальную переменную с именем gCanStart к методу clear() и установить ее равной false. Затем необходимо изменить addBtn, которая вызывается для кнопок Start и StartGrey так, чтобы она учитывала вновь появившуюся gCanStart. Новый код будет выгля- выглядеть следующим образом: Toolbar.addBtn("Start", "graphics/auto.gif", "Start Slideshow", 0, "gIsRunning=?alse && wgCanStart=true", "changeSlide ('auto') ") ; Toolbar.addBtn("StartGrey", "graphics/ *•autoGrey.gif", "Start Slideshow", 0, *¦¦ "gIsRunning=true || gCanStart=false", "") ; Затем потребуется вставить в раздел <head> после- последнего слайдового документа следующий сценарий: <script language="JavaScript"> <! — var savedState; savedState = parent.gCanStart; parent.gCanStart=false; parent.Toolbar.print(parent.frames[2].document); parent.gCanStart=savedState; </script> И наконец, необходимо добавить еще один вызов метода print () объекта Toolbar, срабатывающий при вы- выходе из документа: <body onUnload="parent.Toolbar.print(parent. wframes [2] .document) "> Приведенная строка кода вернет инструментальную панель в предыдущее состояние после перехода к сле- следующему слайду. Если при переходе к следующему слайду устанавли- устанавливаются глобальные переменные и обновляется инстру- инструментальная панель, исчезает необходимость обновления инструментальной панели через обработчик событий on Unload. Используя подобный подход, можно в каж- каждом документе определять, какие кнопки отображать, зная, что эта информация будет сбрасываться каждый раз при загрузке следующего документа. Использование приложения Slide Show На сопровождающем CD-ROM находится каталог, со- содержащий все файлы, необходимые для приложения Slide Show. Для активизации мультифреймового окна просто загрузите slideshow.htm в браузер. Инструмен- Инструментальная панель используется здесь для передвижения по> слайдам и по соответствующим их описаниям. Рисунок 28.1 демонстрирует, как приложение Slide Show выгля- выглядит после загрузки в браузер. В программу входят пять слайдов. Инструментальную панель можно использовать для продвижения вперед или назад по слайдам (соответственно, с помощью третьей и второй кнопок). Можно также воспользоваться первой и четвертой кнопками для перемещения к первому и последнему слайду. Последние две кнопки справа запус- запускают и останавливают продвижение по слайдам. Обра- Обратите внимание, что последняя кнопка недоступна и ото- отображается соответствующим образом. Это кнопка StartGrey. После щелчка на кнопке Start (с изображе- изображением стрелки вправо и эллипса) программа слайдовой
Навигация по сайту с использованием JavaScript демонстрации начинает циклически проходить по каж- каждой паре HTML-документов. На рис. 28.2 показан экран браузера в процессе слайдовой демонстрации. Обратите внимание, что кнопка останова доступна, тогда как кнопка Start — нет. \Щ- JavaScript Unleashed - Nolscnpc I ¦ ¦¦ > ¦¦¦'¦-•St:-r :V" Faster tilting a stroll РИСУНОК 28.1. Инструментальнаяпанелъ приложения Slide Show. avaScript Unleashed - Nelscope ?i!e ^Cowith big ears. .И m га РИСУНОК 28.2. Слайд в процессе выполнения программы слайдовой демонстрации. Обсуждение дополнительных возможностей Ключевой объект buttonSet можно изменить еще боль- больше. Например, его можно модифицировать с целью обеспечения поддержки вертикальных инструменталь- инструментальных панелей вместо горизонтальныхлибо даже для реа- реализации обоих видов панелей. Для этого просто измените метод print(), добавив после каждой кнопки дескриптор <br>. Можно также создать инструментальную панель в отдельном окне браузера. Такая панель может исполь- Глава 28 зоваться как навигационный инструмент или даже как справочное меню. Никакие модификации для этого не требуются. Просто передайте в метод print() объект Document нового окна. Использование объекта History До сих пор рассматривались способы навигации по пред- предварительно созданным Web-страницам. Но что если на Web-странице необходимо обеспечить навигационные средства управления, которые обладали бы функцио- функциональными возможностями, характерными для инстру- инструментальных панелей браузеров? К счастью, JavaScript предоставляет специальный объект History, который позволяет передвигаться по Web-сайтам, которые бра- браузер отображал ранее. В том числе и по Web-страницам, которые создавали не вы. Объект History способен это делать, поскольку в нем хранится список всех посещен- посещенных URL-адресов. Для навигации по списку URL объект History име- имеет некоторые встроенные методы навигации вперед и назад. Метод backO загружает URL предыдущего посе- посещенного Web-сайта. Метод forward() загружает следу- следующий URL в списке посещений. Кроме того, объект History имеет еще один метод и ряд свойств. К сожалению, из соображений безопасно- безопасности многие браузеры не позволяют использовать допол- дополнительный метод и свойства. В действительности, это не очень большой недостаток, поскольку большинство возможностей объекта History реализовано в методах back() и forward(). Для демонстрации применения объекта History сто- стоит создать простенькую страницу, которая содержит всего две навигационных кнопки. Одна кнопка будет пе- переводить пользователя на предыдущий URL из списка посещений, а другая — на следующий URL в этом спис- списке. Кнопки будут использовать свои обработчики собы- событий onClick для вызова двух методов History, которые обсуждались ранее. Код такой Web-страницы показан в листинге 28.6. Листинг 28.6. Использование объекта History для целей навигации. <html> <head> <title>Using the History object</title> </head> <body> <center> <hl>Navigating with the History object</hl> Press one of the following buttons to navigate. <hr> <form>
Избранные программные технологии Часть V <input type="button" value="Back" onClick="window.history.back()"> <input type="button" value="Forward" onClick="window.history.forward()"> </form> </center> </body> </html> Для исследования особенностей работы кнопок нач- начните с загрузки одного из предпочитаемых Web-сайтов (попробуйте www.diasoft.kiev.ua). Как только Web-сайт загрузится, напечатайте URL-адрес, используемый в листинге 28.6. Затем введите URL другого не менее любимого сайта (www.osadesign.com), который отлича- отличается от URL первого загруженного сайта. Теперь щелк- щелкните на кнопке "Back" в панели браузера. В браузере отобразится Web-страница, показанная на рис. 28.3. Теперь можно использовать навигационные кнопки для перехода на любой из только что посещенных Web-сай- Web-сайтов. Резюме JavaScript может выполнять несколько действий сразу, следовательно, появляется возможность создавать более сложные навигационные средства. За счет нажатия пользователем всего лишь одной кнопки JavaScript мо- может верифицировать данные, отправлять формы, обнов- обновлять фреймы, а также изменять содержимое других фреймов. Ий- Using the History object - Neturapn Go Navigating with the History object Press one of tht following buttons to nawgate РИСУНОК 28.3. Навигация с использованием объекта History. На примере инструментальной панели был проде- продемонстрирован способ обновления HTML-страницы для создания иллюзии доступности/недоступности кнопок во время взаимодействия с ними. Также был показан метод изменения содержимого трех фреймои одним щелчком на кнопке. Объект buttonSet с небольшими модификациями несложно применять при проектиро- проектировании других Web-страниц. Объект History предоставляет пользователям функ- функциональные возможности Web-браузера за счет создания на Web-страницах кнопок "Forward" и "Back". Это мо- может оказаться предельно полезным при создании окон, которые не содержат нормальные инструментальные панели браузера, но при этом нужда.тся в манипуляци- манипуляциях ранее посещенными страницами.
Формы и верификация данных В ЭТОЙ ГЛАВЕ Установка пользовательской обратной связи Верификация данных, введенных пользователем Создание интерактивных форм Создание повторно используемого кода верификации Пример: тестер цветов JavaScript После выхода HTML 2.0 у разработчиков появилась возможность создавать на Web-страницах интерактив- интерактивные формы. HTML обеспечивает механизмы создания таких форм: Клиент-серверная модель. Web-браузер поддержива- поддерживает общий графический пользовательский интерфейс (GUI), запускаемый специальным HTML-сценари- HTML-сценарием. С помощью CGI-программы на серверной части могут реализоваться определяемые доменом процес- процессы. Независимость от платформы. Web-браузер работа- работает со множеством платформ. Во время разработки форм не стоит беспокоиться о специфике платфор- платформы. Прозрачность сети. Сетевые коммуникации встрое- встроены в пару Web-6pay3ep/Web-cepBep и реализованы через протокол HTTP. Стандартизованный GUI. Формы были стандартизо- стандартизованы под HTML 2.0. Пользователь, знакомый с эле- элементами формы, может применить эти знания при создании любых форм для Web либо для корпоратив- корпоративной сети. Интерфейсу HTML-форм присущи свои недостатки: • Динамическая обратная связь с пользователем. У HTML-формы нет средств для обеспечения динами- динамической информации по запрашиваемому вводу на основе элемента формы. Проверка формы клиентской части. HTML-формы не могут осуществлять проверку отдельных элементов формы, набора элементов или целой формы клиен- клиентской части. ¦• Диалоговые окна. HTML-формы не могут динами- динамически предупреждать пользователя об ошибках вво- ввода или выдавать запрос на дополнительный ввод. Подтверждение пользователя. Формы не могут зап- запрашивать подтверждение перед выполнением необра- необратимых действий. Интерактивность элементов формы и окна. В HTML- формах интерактивность ограничивается обработкой CGI-кода на серверной части. Для JavaScript характерны эти недостатки. Этот язык строится на основных свойствах HTML и создает более мощный GUI-интерфейс клиентской части. В главе чи- читатель познакомится с методами внедрения таких свойств в JavaScript. LjiaBy завершает приложение, написанное на JavaScript. Все эти возможности применялись с це- целью внедрения инструментальных средств выбора цве- цветов текста и фон. Изрядное внимание в главе уделяется обработчикам событий. Их можно рассматривать как обратные вызо- вызовы, связанные с формой или ее элементами. Они явно ¦определяются как часть формы или дескриптора эле- элемента формы. Обработчики событий вызываются при наличии события, инициируемого пользователем. Они поочередно вызывают определенный фрагмент или фун- функцию кода JavaScript. В табл. 29.1 перечислены обработ- обработчики событий JavaScript.
Избранные программные технологии Часть V Таблица29.1 Обработчики событий JavaScript Обработчик событий Связанные объекты Генерируемое событие onBlur onChange onClick onFocus OnKeyDown OnKeyPress Button, Checkbox, Text, Textarea Radio, Select, Text, Textarea Button, Checkbox, Button, Checkbox, Text, Textarea Textarea Textarea Radio, Radio, Select, Submit, Link, Reset, Submit Select, Submit, Textarea Window OnMouseDown Button Link OnMouseUp Button OnReset onSelect onSubmit OnUnload Form Text, Textarea Form Window Объект Form теряет фокус ввода. Значение объекта Form изменяется. Выполнен щелчок на объекте формы. Объект Form получает фокус ввода. В пределах объекта Form выполнено нажатие клавиши. В пределах объекта Form выполнено нажатие и отпускание клавиши. В пределах объекта Form выполнено отпускание кнопки. Web-браузер завершил загрузку объекта Window. В рамках объекта Form выполнено нажатие кнопки мыши. Пользователь перемещает курсор мыши над ссылкой. В рамках объекта Form выполняется отпускание кнопки мыши. Форма была сброшена. Пользователь выбрал текст в рамках объекта Form. Форма была отправлена. Пользователь завершил работу с окном. Установка пользовательской обратной связи Если форма разработана качественно, пользователь смо- сможет легко и быстро определить вид запрашиваемой инфор- информации. В простых формах подобное задание идеально' выполняется с помощью продуманных меток, прилега- прилегающих к каждому элементу формы. В сложных формах потребуется задействовать детальное объяснение спосо- способа заполнения формы. С помощью JavaScript можно ввести пользовательский запрос дополнительных дан- данных, относящийся к каждому полю. Эта возможность позволяет обеспечивать дополнительную информацию о запросах, функциях, элементах формы в тот момент, когда она необходима. Проделывая такую операцию, можно уменьшить объем текста, используемого для обо- обозначения элементов формы, атакже упростить внешний вид формы. Подсказки пользователям реализуется через обработ- обработчики событий JavaScript и строку состояния браузера. Обработчик событий onFocus можно применить для выполнения функции, определяемой пользователем, в момент, когда объект Form получает фокус ввода. Точ- Точно так же, обработчик событий onMouseOver применя- применяется для выполнения функции, определяемой пользо- пользователем, независимо от того, в каком месте над ссылкой располагается указатель. Эти обработчики событий мож- можно использовать для вызова функции, выводящей на экран командную строку в строке состояния браузера. Создание формы для обратной связи пользователем Следующий пример проиллюстрирует поддержку с по- помощью JavaScript обратной связи в строке состояния браузера. Представьте себе на минутку, что необходи- необходимо создать интерфейс HTML-формы для усовершен- усовершенствованного автоматического тостера. Основная цель — создание простого интерфейса, с помощью которого первый встречный сможет приготовить аппетитный тост. На рис. 29.1 показан пример такого интерфейса. I The Amazing Automated Toaster I Bread Product: laW" ' Quantity: (Г Toastiness:|5oj Buttered: Yes й No с РИСУНОК 29.1 Форма автоматического тостера.
Формы и верификация данных Пользователь может установить значения четырех вводимых объектов: • Объект Selection, представляющий вид хлеба. • Объект Text, представляющий ожидаемое количество кусочков хлеба. • Объект Text, представляющий степень поджаривания (в цифрах). ¦ • Два переключателя, указывающих, добавлять ли мас- масло. Объекты Selection и Text связаны с обработчиками событий onBlur и onFocus. Эти обработчики выводят на экран и перемещают определенные пользовательские строки, связанные с введенными объектами. Обработ- Обработчик событий onClick увязывает переключатели с фор- формой обратной связи. Свойство window.defaultStatus устанавливается для вывода сообщений приветствия по умолчанию, когда поступление другой информации отсутствует. Код для примера с тостером показан в листинге 29.1. Поскольку в действительности тостера нет, после запол- заполнения формы код отсылает почту. В этом листинге не- необходимо заменить адрес на текст your_mail_ID. Каж- Каждый раз когда встречается часть кода в скобках, его необходимо заменять на информацию, зависящую от пользователя или сайта. Тестирование пользовательской формы CGI-программы обычно составляются с целью обработ- обработки данных со всей формы. Однако, возможно, потребу- Листинг 29.1 toaster.htnii Глава 29 ется создать форму еще до того как CGI-программа бу- будет доступна. Может быть, необходимо отладить фор- форму без обращения CGI-программы. Ниже приводятся простые способы проверки формы, обходящие CGI- программу: Для большинства сайтов доступна CGI-программа с именем test-cgi, если в форме используется метод get. Воспользуйтесь следующим дескриптором: <f ormaotion=http : //your_site_name /cgi-bin/ gi method="get"> После отправки формы пользователь получает стра- страницу, содержащую, помимо других элементов, зна- значения элементов формы из передаваемой страницы. Несмотря на то что CGI-файл test-cgi поддержива- поддерживается многими серверами, его точное расположение и доступность могут зависеть от сайта. Администратор Web-сайта сможет сообщить читателю о деталях. CGI-программа post-query доступна на большинстве сайтов, если форма использует метод post. Исполь- Используйте следующий дескриптор формы: <form action=http://your_site_name_/cgi-bin/ ^test-query method="post"> После отправки формы пользователь получает стра- страницу, содержащую, помимо других элементов, пары имя/значение, соответствующие элементам передава- передаваемой формы. Несмотря на то что post-query поддер- поддерживается большинством серверов, его точное распо- расположение и доступность могут зависеть от сайта. О' деталях вам сообщит администратор Web-сайта. <!— ИеЬ Page for controlling an automated toaster — Note: Since we don't really have an automated mail the results back to the developer <html> <head> <title>The Amazing Automated Toaster</title> <script language="JavaScript"> <!— начало сценария function setstatus(str) toaster —> window. status = str; return true ; 1 var greeting="Hello! How about some nice toasted bread products!1"; window.defaultStatus = greeting; ,// окончание сценария —> </scri;?t> </head> <body> <hl>The Amazing Automated Toaster</hl> <?orm action="mailto:your_mail_ID" method="post"> <font size=5>Bread Product:</font> <select name=tfproduct"
Избранные программные технологии Часть V onFocus="setstatus('select desired bread product from list.1)" onBlur="setStatus('')"> <option>Bread <option>Waffle < option>B agel <option>Roll <option>Muffin <option>Croissant <option>Scone </select> <br> <font size=5>Quantity:</font> <input type="text" name="quantity" value="l" size=4 maxlength=4 onFocus="setstatus( 'Enter quantity of bread products desired A-1000). ¦) " onBlur="setStatus('')"> <br> <font size=5>Toastiness:</font> <input type="text" name="toastiness" value="S0" size=3 maxlength=3 onFocus="setstatus(" Enter degree of toastiness from 0-100 @=untoasted 100=burnt).')' onBlur="setStatus('')"> <br> <font size=5>Buttered:</font> <font size=5>Yes</font> <input type="radio" name="buttered" value="yes" checked onciick="setstatus('Do you want butter on the bread product?')"> <font size=5>No</font> <input type="radio" name="buttered" value="no" onClick="setstatus('Do you want butter on the bread product?')"> <hr> <input type="submit" value="Start Toaster"> <input type="reset"> </form> </body> </html> Если в форме применяется метод post, можно сде- сделать так, чтобы результаты отправлялись на вашу учетную запись. Воспользуйтесь следующим деск- дескриптором формы: <form action="mailto:your_maiI_ID" method="post"> После отправки формы пользователь получает по электронной почте сообщение, содержащее пары имя/значение, соответствующие элементам формы из передаваемой страницы. (Используя Netscape Navigator и Microsoft Internet Explorer, пользователь получает предупреждение перед отправкой формы по электронной почте. Это не ошибка, а всего лишь мера предосторожности. Пользователь уведомляется о том, что получатель формы сможет увидеть адрес пользователя в заголовке сообщения. Иначе говоря, отправка формы по почте не является анонимной.) Вывод окон сообщений JavaScript обладает несколькими способами связи с пользователем через всплывающие окна предупрежде- предупреждения и два вида диалоговых окон. Эти методы применя- применяются для передачи пользователю важной информации, подтверждения выбора и запроса дополнительной ин- информации. Окна предупреждения часто используются при отладке. Метод alertQ обеспечивает передачу пользователю короткого сообщения. Он является методом объекта Window. Для его активизации определять объект Window не обязательно. Метод alert() можно применять для со- сообщения пользователю об ошибке ввода, как показано в следующем коде: alert {"Error: value outside valid range of 0 to ^«240 volts.") Именно благодаря этой строке кода осуществляет- осуществляется вывод сообщения на экран (см. рис. 29.2): РИСУНОК 29.2 Предупреждающее сообщение.
Формы и верификация данных Кроме того, метод alertQ можно использовать как помощь при отладке, скажем для вывода строки, содер- содержащей отладочную информацию: var dlxjstr = "Value of 'wattage' = " + wattage; alert(dbgstr); Такой метод применяется для трассировки програм- программы на JavaScript: function CalculateWattage (volts, amps) ¦I var dbgstr = "CalculateWattage < " + volts + 11," + amps + " ) " ; alert(dbgstr) ; Каждый раз при вызове функции CalculateWattage() всплывает предупреждающее сообщение, указывающее на вызов и передаваемые аргументы. По завершении процесса отладки программы код отладки можно уда- удалить или закомментировать. Более детальная информа- информация по использованию окна сообщений для отладки кода JavaScript приводится в главе 34. Метод confirm() похож на метод alert(), однако по- позволяет отвечать на сообщение. Ответы ограничены дву- двумя вариантами — ОК и Cancel (Отмена). Если пользо- пользователь выбирает ОК, метод возвращает true, а если Cancel — значение false: function submitCallback() ! if (selfDestructSelected == true) return confirm ("Invoke self-destruct *-• mechanism in 60 seconds?"); else return true <f orm onSubmit="return submitCallback()"> Этот код вызывает отображение диалогового окна подтверждения (рис. 29.3). РИСУНОК 29.3Диалоговое окно подтверждения Щелчок на ОК приводит к продолжению передачи. При нажатии Cancel возвращается false, которое посту- поступает в объект Form и препятствует отправке формы. Метод prompt() — еще один метод Window. Он обес- обеспечивает возможность ввода пользователем произволь- произвольного значения: var f.ivColor=prompt ("What\ ' s your favorite color?") Можно указать необязательный второй аргумент, который рассматривается в качестве значения по умол- умолчанию: Глава 29 var duration=prompt ("Enter duration in ^months: " , 6) ; Эта строка кода обеспечивает отображение диалого- диалогового окна, которое показано на рис. 29.4. РИСУНОК 2 9, ^Диалоговое окно ввода Пользователь обычно вводит информацию через эле- элементов ввода на форме, а диалоговое окно ввода долж- должно применяться лишь в редких случаях, когда существует настоятельная потребность в такого рода информации. В следующем примере осуществляется запрос адреса электронной почты пользователя. <html> <scrlpt language="JavaScript"> <!—начало сценария> function sendEmail(formObj) f if(formObj.emailSpecials.checked) { ans = prompt ("Please enter your email ^-address."); formObj.email.value=ans; //конец сценария--> </script> <center> <hl>Bob's Music Store</hl> To receive our free catalog by mail please enter your email address below. <form name="addressForm" onSubmit="sendEmail(this)"> <table> <tr> <td>Name:</td> <tdxinput type="text" name="name"X/td> </tr> <tr> <td>Address</td> <tdxinput type="text" name="address"X/td> </tr> <tr> <td>City</td> <tdxinput type="text" name="city"X/td> </tr> <tr> <td>State</td> <tdxinput type="text" name="state"x/td> </tr> <tr> <td>Zip</td> <tdxinput type="text" name="zip"x/td> </tr> <tr> <td colspan=2Xinput type="checkbox" name="emailSpecials"> Please email me about special deals !</td>
Избранные программные технологии Часть V <input type="hidden" name="email" value= <input type="submit" name="submit" value="Submit"> </form> </center> </html> i^НАПОМИНАНИЕ *" j2— Когда всплывает диалоговое окно или окно сообщения, пользователь должен переключить внимание на окно и соответствующим образом ответить. Именно по упо- упомянутой причине предупреждающие сообщения и ди- диалоговые окна не рекомендуется использоваться очень часто. .Использование сообщения о состоянии Другой способ обеспечения обратной связи с пользова- пользователем во время ввода данных предполагает использова- использование сообщений о состоянии. Сообщения о состоянии — это те фразы, которые можно наблюдать в строке состо- состояния в нижней части окна браузера. JavaScript позволяет изменять все, что представляется в этой строке. Это дает возможность отправлять пользователю сообщения, во время его взаимодействия с HTML-формой. Считается, что сообщения в строке состояния в меньшей степени отвлекают внимание пользователя по сравнению с диа- диалоговыми окнами, однако им присущ один недостаток — они менее заметны. В листинге 29.2 показан пример использования дополнительной помощи во время вво- ввода данных. Листинг 29.2 Отображение сообщения о состоянии <html> <head> <title>JavaScript Unleashed</title> <script language= "JavaScript"> <! function statusMsg(msgType) { var message = ""; if (msgType = "string") { message = "Any characters can be used if(msgType = "integer") { message = "Please enter a whole number I else if (msgType = "dollar") { message = "Please enter a dollar amount '¦'here, (e.g. 19.99)"; else if (msgType = "credit") { message = "Please enter a credit card '"number here. Do not use dashes . " ; I window.defaultStatus = message; window.status = message; ";i II—> </script> </head> <body onFocus="statusMsg('')"> <form name="forml" action="#" method="post"Xbr> First Name <input type="text" size=20 maxlength=20 name="Integer" onFocus="statusMsg(' string1) "Xbr> Last Name <input type="text" size=20 maxlength=20 name="Integer" onFocus="statusMsg(' string') "Xbr> Age <input type="text" ,size=5 maxlength=5 name="Integer" onFocus="statusMsg ('integer') "Xbr> Amount <input type="text" ,size=6 maxlength=6 name="Dollar" onFocus="statusMsg ('dollar') "Xbr> Card # <input type="text" size=16 maxlength=lб name="Credit" onFocus="statusMsg (' credit1 > "Xbr> <br> <input type="submit" value="Submit"> </form> </body> </html> Когда пользователь перемещает курсор на поле либо же его автоматически помещает туда браузер, обработ- обработчик событий onFocus вызывает функцию statusMsg(). В сроке состояния выводится соответствующее сообщение за счет установки свойства status объекта Window. Фун- Функция statusMsg() позволяет очистить строку состояния, передавая в нее пустую строку. Очистка происходит в случае щелчка на любом месте окна браузера за преде- пределами текстовых элементов. При этом активизируется обработчик событий onFocus, сбрасывающий сообщение о состоянии. «НАПОМИНАНИЕ ^-. Щ .Щ^Г?ГЖ™^ Щ W Неплохо также установить свойство окна defaultStatus для вывода на экран того же сообщения о состоянии. Разработчик может не волноваться по поводу того, что его сообщение исчезнет, как только пользователь протащит указатель мыши по экрану. Подобный спо- способ идеален и в случае применения фреймов, когда требуется "приклеить" сообщение, даже если пользо- пользователь передвигает указатель мыши в другой фрейм.
Формы и верификация данных Верификация данных, введенных пользователем Перед появлением JavaScript верификация формы осу- осуществлялась CGI-программой. Такой подход был эф- эффективным, но требовалось, чтобы вся форма была пол- полностью заполненной и переданной на сервер до соб- собственно процесса верификации. В некоторых средах, например, с низкоскоростным соединением с World Wide Web, может произойти существенное отставание между моментами передачи формы и возврата сообще- сообщения о найденной ошибке. Более того, ожидая передачи формы на верификацию, пользователь не получит об- обратную связь до тех пор, пока вся форма не будет за- завершена. Непосредственная обратная связь исключи- исключительно важна, поскольку пользователь только что ввел информацию и в настоящий момент он может воспри- воспринять обратную связь в соответствующем контексте. Быстрая обратная связь может повлиять на последую- последующее поведение пользователя и снизить количество оши- ошибок, связанных с заполнением формы. И наконец, на Web-странице обычная CGI-программа уведомляет об ошибках ввода. Пользователь должен вновь вернуться к форме, чтобы внести необходимые изменения, что пре- прерывает естественный процесс ввода данных в форму. Верификация ввода данных в форму Для проверки корректности информации в текстовых элементах формы используются два обработчика собы- событий. Обработчик событий onBlur вызывается, когда эле- элементы текста или текстовой области формы теряют фо- фокус ввода. Обработчик событий onChange вызывается, когда происходит изменение содержимого элемента тек- текста или текстовой области. Говорят, что элемент имеет фокус, если любые дан- данные, вводимые пользователем, направляются именно в этот элемент. Когда текст или текстовая область элемента обладают фокусом, это значит, что текстовый курсор находится именно на данном элементе. При переклю- переключении пользователя на другой элемент (с использовани- использованием мыши или клавиши табуляции), начальный элемент теряет фокус. Обработчик onBlur вызывается каждый раз, когда поле ввода теряет фокус. Пользователь может поменять данные в поле либо же оставить их неизменными. Об- Обработчик событий может вызывать верификационный код для неизмененных данных или значений по умол- умолчанию в поле. Для этого потребуется соответствующим образом приспособить код. Обработчик событий onChange вызывается только в случае изменения содержимого поля. Если пользователь сразу же выбирает поле (возможно, для просмотра об- обратной связи в строке состояния), а затем другое поле, Глава 29 обратный вызов, определенный пользователем, уже не выполняется. Несмотря на свою эффективность, этот метод имеет свои недостатки. Предположим, что пользо- пользователя необходимо предупредить о вводе неверных дан- данных в поле. Если пользователь производит щелчок на поле, а затем передумывает вносить изменения, или же набирает те же неправильные данные, это не будет рас- рассматриваться как изменение. В таком случае запуск об- обработчика событий onChange не выполняется. Поэтому, если решено применять onChange, потребуется прове- проверять введенные данные во время передачи (через обра- обработчики событий onSubmit и onCIick). В следующем примере организуется текстовое поле для ввода количества элементов. Корректными значени- значениями являются 100 и 1000. Обработчик событий onBlur вызывается для запуска функции верификации. Тексто- Текстовый объект ввода передается в обработчик. Если введен- введенные данные не верны, происходит следующее: Всплывает окно предупреждения, уведомляющее пользователя об ошибке. • Фокус ввода возвращается в текстовое поле. • Текст выделяется (иподсвечивается), и поэтому его можно легко распознать. ¦Обратите внимание на то, что обработчик onFocus обеспечивает для текстового поля пользовательскую об- обратную связь — возможно, для того, чтобы проинфор- проинформировать пользователя о минимальных и максимальных указаниях: function validateQuantity (quantobj) if <quantObj .value < 100) alert("Minimum order quantobj.focus(); quantobj.select(); 100 units."); else if (quantObj.value > 1000) { alert("Quantities greater than 1OOO " 4- "units require special order.") quantobj.focus(); quantobj.select(); 3 return; <h2>Enter number of units:</h2> <input type="text" name="quantity" value=00" length=4 maxlength=4 onFocus="quantFeedback()" onBlur="validateQuantity (this) ">¦ Обеспечение согласованности Иногда между несколькими полями ввода существует взаимосвязь. На рис. 29.5 показана часть формы, запол-
Избранные программные технологии Часть V няемой данными о бюджете отдела. Пользователь дол- должен ввести общий бюджет, а затем распределить его по трем категориям. П-": Department BudgBt- Netscape ¦ Ble Edit ^iew ?u~<?anirncriice!or !^*rp ¦¦ . Department Budget Total Budget (OOO's dollars Salaries (OOO.'s dollars) i Expenses {000's dollars) : Capital Equipwen dollars) : ПН Г " " '". ¦ J |2000 A300 J30 0 I-JOO 1 i ¦ Ш n\x\\ ., a; .-i.-.v ¦¦.,¦.:¦¦.- .-¦.".!'.¦:¦. ..¦ ¦¦¦ РИСУНОК 29.5 Форма для ввода данных о бюджете В сумме три категории должны формировать общий бюджет. Перед появлением JavaScript проверка суммы была невозможной до передачи формы на обработку Gl-программой. С появлением JavaScriipt ситуация изменилась: верификация суммы возможна до отправ- отправки формы, что экономит время пользователя и сохра- сохраняет рабочий контекст (т.е. перед и после проверки Web-страница остается неизменной). Ниже показана часть кода такой формы: <form name="myform" method="post" action="actionURL" onSubmit=" return validateBudget(myform)"> <h2>Department Budget<7h2> <pre> Total Budget [OOO's dollars): <input type="text" name="totalBudget" value=" onBlur="validateNumeric(this)"> Salaries (OOO's dollars): <input type="text" name="salaries" value=" onBlur="validateNumeric(this)"> Expenses (OOO's dollars): name="expenses" value=" onBlur="validateNumerio(this)"> Capital Equipment @0 type="text" name="capital" value=" onBlur="validateNumeric(this)"> </pre> <input type="submit" name="submit" value="Submit"> </form> Обработчик событий onBlur вызывает пользователь- пользовательскую подпрограмму верификации, которая следит, что- чтобы пользователь вводил корректные цифровые данные в каждое поле. Показанная ниже функция необходима для проверки совпадения суммы категорий с общим бюджетом: function validateBudget(formObj) i var calcBudget = parselnt(formObj.salaries.value,10) + parselnt(formObj.expenses.value,10) + parselnt(formObj.capital.value,10); var totalBudget = parselnt(formObj.totalBudget.value,10); if (calcBudget != totalBudget) { alert("Error: total budget is not equal + "sum of allocations."), return false; else return true; :i Эта функция отображает окно предупреждения, если допущена ошибка, и приостанавливает процесс. ПРЕДУПРЕЖДЕНИЕ Язык HTML все еще пребывает в развитии. В большин- большинстве случаев браузеры игнорируют незнакомые деск- дескрипторы или ключевые слова, которые могут изменять- изменяться в стандарте HTML либо в расширениях HTML, поддерживаемых разными поставщиками. Это очень выгодно пользователям Web-браузеров, поскольку ник- никто не желает, чтобы браузер аварийно завершался каждый раз, когда он встречает незнакомый дескрип- дескриптор или ключевое слово. В большей степени упомянутая проблема касается программистов, работающих с JavaScript. Если разра- разработчик допустил ошибку в написании имени обработ- обработчика событий или другого ключевого слова внутри дес- дескриптора HTML, программа должным образом функ- функционировать не будет, а браузер не укажет на ошибку. Используя в форме обработчики событий JavaScript, не мешало бы проверить код на присутствие (аналь- (анальных опечаток. Обеспечение бизнес-правил Стратегия, относящаяся к форме, должна передаваться пользователю через поясняющие тексты внутри формы либо через отдельный справочный документ (соответ- (соответствующим образом связанный с формой), а может, и обоими способами. JavaScript можно задействовать для проверки соответствия этой стратегии (бизнес-правил) ввода данных. Предположим, что форма позволяет определять день перевозки груза, но при этом имеется бизнес-правило, запрещающее осуществлять перевозку в выходные. При помощи кода JavaScript несложно проверить, не выпа- выпадает ли перевозка на выходные. Таким образом удовлет- удовлетворяется это бизнес-правило: ,// Вычислить дату погрузки, исходя из данных, // введенных пользователем. Возвращав' // объект date. function calcShipDate(formObj) var day = parselnt(formObj.shipDay.value);
Формы и верификация данных var month = parselnt(form0bj.shipMonth.value); var year = parselnt(formObj.shipYear.value); var hrs = 0; var min = 0 ; var see = 0; shipDate = new Date(year,month,day,hrs,min,sec) . return shipDate; I // Проверка бизнес-правила, касающегося погрузки / / — не отправлять груз в выходные. // Проверка, не относится ли дата к // прошлому или текущему времени. function shippingPolicy (formObj) { var shipDate = calcShipDate (formObj) ; var day = shipDate . getDay () ; var currentDate = new Date(); i f (shipDate.getTime() < *¦>currentDate .getTime () ) { alert ("Error: ship date must be *¦ future date. ") ; formObj.shipDay.focus(); formObj.shipDay.select(); return false; if (day =0) { alert ("Sorry, we cannot ship on '-'Sunday.1') ; formObj.shipDay.focus(); formObj. shipDay. select( ) ; return false; ) else if (day =6) { alert ("Sorry, we cannot ship on ^Saturday."); formObj. shipDay. focus() ; formObj.shipDay.select(); return false; -> else return true ; <form name="myform" method="post" action="actionURL" onSubmit="return shippingPolicy(myform)"> Если пользователь вводит дату, приходящуюся на субботу или воскресенье, он уведомляет о соответству- соответствующем бизнес-правиле. На поле ввода даты устанавли- устанавливается фокус, информация в нем выделяется, а форма не отправляется. Код также накладывает запрет на пе- перевозку груза в тот же день. ПРИМЕЧАНИЕ Проверяя даты с использованием JavaScript, необхо- необходимо помнить, что время и дата соответствуют на- настройкам на пользовательском компьютере. Возмож- Возможно, клиентские и серверные программные средства работают в различных временных зонах. Кроме того, существует ненулевая вероятность некорректной ус- Глава 29 тановки времени на клиентской части, т.е. ошибочной даты или времени. Проверка на завершенность Формы, в основном, состоят из набора обязательных и необязательных полей. При отсутствии обязательных полей форма не сможет функционировать должным об- образом. И опять-таки, для проверки присутствия этих полей можно воспользоваться JavaScript. В следующем примере рассматривается форма, зап- запрашивающая у пользователя контактную информацию (см. рис. 29.6). В данном случае обязательными поля- полями являются имя, адрес, домашний номер телефона, а все остальные поля — необязательны. Contact Information (U.S.) Last Name; |Latta Address: J1632 Caffenin» Way City/Town: 'Бхргевво j stafe: [f>^! Zip Code: J7B_260, Home phone:p Wort Phone :|= PAX: iO2-5S5-1643 E-mail Address: |I Quest: \?° 1_earn . Ja.va?<\ Favorite Color: j РИСУНОК 29.6 Форма сконтактнойинформацией После передачи формы вызывается функция вери- верификации. Если одно из обязательных полей пусто, пользователь уведомляется об этом и форма не отправ- отправляется. Код для формы с контактной информацией показан в листинге 29.3. Листинг 29.3 contacthtm <html> <head> <title>Contact Information</title> <script language="JavaScript"> <!-- Начало сценария // Проверка, заполнены ли все обязательные поля function validateComplete(formObj) if (emptyField(formObj.firstName)) alert("Please enter your first name."); else if (emptyField(formObj.lastName)) alert("Please enter your last name."); else if (emptyField(formObj.addressl) ss emptyField(formObj.address2)) alert ("Please enter your address.");
Избранные программные технологии Часть V else if (emptyField(formObj.city)) alert("Please enter your city or else if (emptyField(formObj.state)) alert ("Please enter your state."),- else if (emptyField(formObj.email)) alert("Please enter your E-mail waddress."); else return true; return false; // Проверка, является ли поле пустым function emptyField (textobj) { if (textObj .value, length = 0) return true; for (var i=0; KtextObj .value.length; ++i) { var ch = textobj ,value.charAt(i); if (oh != ' ' ?& ch != '\t') return false ; i return true ; // Конец сценария --> </script> </head> <body> <hl>Contact Information (U.S.)</hl> <form name="myform" action="actionURL" method="post" onSubmit="return validateComplete (document .myform) "> <pre> First Name: <input type="text" name="firstName"> Last Name: <input type="text" name="lastName"> Address: <input type="text" name="addressl"> <input type="text" name="address2"> </pre> City/Town: <input type="text" name="city" size=12> State: <input type="text" name=" state" size=2> Zip Code : <input type="text" name="zip" size=5> <pre> Home Phone :<input type="text" name="homePhone" size=12> Work Phone:<input type="text" name="workPhone" size=12> FAX: <input type="text" name="FAX" size=12> E-mail Address: <input type="text" name="email"> Quest: <input type="text" name="quest"> Favorite Color: <input type=Mtext" name="favColor"> </pre> <hr> <input type="submit" name="submit" value="Submit"> </form> <body> <html> Код реализует очень базовую проверку — считает- считается, что поле присутствует, если оно не пустое. В дан- данном случае не вскрывается различие между корректной и некорректной датами, что, однако, достигается до- дополнительной простой проверкой. Например, можно проверить, чтобы строка штата содержала аббревиату- аббревиатуру из двух букв, а номер телефона — требуемое коли- количество цифр. В общем случае, можно выполнять про- простые проверки на клиентской части и более сложные — на серверной. ^ПРИМЕЧАНИЕ ~У' * -:"' '"','' Предыдущий пример реализует форму контактной информации для англоязычных пользователей, про- проживающих в США. Internet — всемирная сеть. В не- некоторых странах за именем следует отчество, штаты отсутствуют, ZIP-коды не применяются, а язык пользо- пользователей - не английский. Однако, любимый цвет есть у каждого. Вопрос интернационализации в данной книге не рассматривается. Несмотря на это, необходимо учитывать место проживания потенциальных пользова- пользователей и соответствующим образом проектировать формы. Создание интерактивных форм Перед появлением JavaScript простейшие интерактив- интерактивные формы должны были взаимодействовать с CGI- программой на сервере. Применяя JavaScript, можно создавать интерактивные формы, где взаимодействие ¦будет полностью проводиться на клиентской части, при этом можно будет не совершать путешествие на сервер- серверную часть. Интерактивное программирование на JavaScript об- обладает несколькими ограничениями. Желательно дина- динамически изменять каждый элемент страницы. После- Последние версии браузеров Netscape и Microsoft динамически изменяют содержимое страницы без обра- обращения к серверу. Все это достигается благодаря DHTML и каскадным таблицам стилей (CSS). К сожалению, эти стандарты все еще совершенствуются и внедряются только в относительной степени. Перед тем как ввести ограничения на использование браузеров, в которых будет работать HTML-файл, необходимо учесть, что после однократной визуализации страницы и формати- форматирования элементов Web-браузер ом, код JavaScript уже ничего не сможет изменить. Если после записи страницы нельзя внести измене- изменения в ее форматирование, что же остается делать? JavaScript позволяет создавать взаимосвязь между следующими элементами: Элементы формы на одной и той же странице. Элементы формы и другое окно. Элементы формы и другие фреймы.
Формы и верификация данных Глава 29 Для совершенствования формы можно воспользо- воспользоваться и ранее описанными методами: обратной связью с пользователем, окнами сообщений, верификацией дан- данных, вводимых пользователем. Можно изменить всю страницу, полностью переписав ее. В этом случае бра- браузер стирает текущую страницу и выполняет полное пе- переформатирование новой страницы. Можно также из- изменить цвет фона страницы (свойство Document), но не цвет текста. Это невозможно, поскольку текст страни- страницы уже был визуализирован в определенном цвете. Использование вычисляемых полей Следующий пример, показанный на рис. 29.7, отлича- отличается от примера с бюджетом, рассмотренного в начале главы. В данном примере появилось новое текстовое поле remainder. Несмотря на то что изменение текста или графики страницы после ее записи невозможно, можно изменять элементы формы. В данном случае про- происходит изменение текстового элемента remainder, зна- значение которого основано на значениях других элементов. Пользователь вводит общий бюджет и другие категории, а после этого в текстовом поле выводится сумма денег, оставшихся после распределения по категориям. . I Ч ¦]¦ Ill.lj-.4l1 iiill! |' ¦ ¦ Сг ¦!::¦. :н ¦ Department Budget |2D00 Total Budget (CCO's dollars): Salaries @00's dollars): Expenses (OOO's dollars): Capital Equipment (OOO's dollars Unallocated Remainder: 1300 \500 РИСУНОК 29.7. Пример вычисляемого бюджета. В этом примере используется обработчик событий onChange для внесения изменений в поле remainder вся- всякий раз, когда меняется одно из значений других тек- текстовых полей. Когда пользователь отправляет форму, сценарий пересчитывает сумму остатка. Если значение ее раьно нулю, форма передается, в противном случае на экран выводится предупреждающее диалоговое окно. Код гримера показан в листинге 29.4: Листинг 29.4. Инструментальное средство введения бюджета отдела. <html> <head> <title>Department <! - начало сценария function calcRemainder(formObj) var calcBudget = parselnt(formObj.salaries.value,10) + parselnt(formObj.expenses.value,10) + parselnt(formObj.capital.value,10); var totalBudget = parselnt(formObj.totalBudget.value); var unalloc = totalBudget - calcBudget; formObj .remainder.value = unalloc; function validateBudget(formObj) calcRemainder (formObj); var unalloc = fortnObj . remainder. value; if (unalloc != 0) { alert("Error: Total budget is not + "to sum of allocations."); return false; i return true ; ) // конец сценария —> </script> </head> <body> <form name="myform" method="post" action="actionURL" onSubmit="return validateBudget(myform)"> <h2>Department Budget</h2> <pre> Total Budget (OOO's dollars): <input type="text" name="totalBudget" value=" onChange="calcRemainder(myform)"> Salaries (OOO's dollars): <input type="text" name="salaries" value=" onChange="calcRemainder(myform)"> Expenses (OOO's dollars): <input type="text" name="expenses" value=" onChange="calcRemainder(myform)"> Capital Eo^iipment (OOO's dollars): <input type="text" name="capital" value=" onChange="calcRemainder(myform)"> <input type="text"* name="remainder" value="> </pre> <input type </form> </body> </html> ="submit" name="submit" value="Submit"> Budget</title> <script language="JavaScript"> JavaScript можно использовать для написания не- небольших интерактивных приложений, где все процес- процессы проходят на клиенткой части. В листинге 29.5 пред- представлены вычисления значения будущих инвестиций. Пользователь вводит начальную сумму, процент, а за- затем количество лет, в течение которых планируется по- погасить инвестиции. На рис. 29.8 показан экран после загрузки сценария в браузер. Обратите внимание, что
Избранные программные технологии Часть V вывод функции calculate() отображается в текстовых полях ввода, как описывалось ранее. Compound Interest Calculator (loop Present Value: I Interest Rate<*): Years. o? c< A2 |6.0 Total interest: Future Value: РИСУНОК 29.8 Форма сложных процентов Здесь не требуется применение CGI-программ по- поскольку все процессы реализуются на стороне клиента. Заметьте, что вместо объекта Submit в форме использу- используется объект Button. Кроме того, вместо обработчика со- событий onSubmit применяется onClick. Семантика объек- объекта Submit и обработчика onSubmit задействуется, когда Web-браузер передает форму на сервер. Однако, по- поскольку требуется, чтобы процессы выполнялись на кли- клиентской части, необходимо использовать обработчик событий onClick и функцию calculate(), когда кнопка нажата. Для достижения большей степени реальности кнопка была названа Calculate, тем не менее, ее назва- название вполне можно изменить и на Submit. До тех пор пока пользователь не просмотрит исходный код страни- страницы, невозможно увидеть, что за HTML используется на клиентской части и CGI-сценарий — на серверной ча- части. Код примера представлен в листинге 29.5. Листинг 29.5 Вычисление сложных процентов <html> •<head> <title>Compound Interest Calculator</title> <script language="JavaScript"> <!— начало сценария function calculate(formObj) ( var presentval = parseFloat(formObj.presentval.value); var intRate = parseFloat(formObj.intRate.value)/100.; var years = parseFloat(formObj.years.value); var futureVal = presentval * Math.pow(A.0+intRate),years); var totallnt = futureVal - presentval ; futureVal = Math. round(futureVal*100 . 0) / 100.0; totallnt = Math.round(totallnt*100.0)/ 100.0; formObj .futureVal.value =¦¦ futureVal, formObj.totallnt.value = totallnt; return; ) // конец сценария —> </script> </head> <body> <hl>Compound Interest Calculator</hl> <form name="myform"> <pre> Present Value: <input type="text" name="presentVal"> Interest Rate(%) : <input type="text" name="intRa te"> Years of Compounding: <input: type=lftext" name="years"> <input type="button" name="calc" value="Calculate" onclick="calculate(myform)"> </pre> <hr> <pre> Total Interest: <input type="text" name="totallnt"> Future Value: <input type="text" name="futureVal"> <pre> </form> </body> <html> Создание повторно используемого кода верификации В следующих разделах рассматриваются способы вери- верификации наиболее общих типов данных, используемых во время работы в Internet. Эти примеры применяются в библиотеках кодов, которые хранятся в отдельном файле либо в исходном документе с набором фреймов. Во всех примерах в качестве одного из аргументов пе- передается объект текстового элемента. Такая возможность позволяет в случае необходимости изменять текстовые поля в процессе проверки данных. Для более специфич- специфичной проверки данных воспользуйтесь регулярными выра- выражениями (Regular Expressions), о которых речь пойдет в главе 31. Целые числа Код, представленный в листинге 29.6, проверяет вводи- вводимые числа, являются ли они целыми. Сценарий вызы- вызывается, как только пользователь щелкает на кнопке Validate. Результат (true или false) выводится в тексто- текстовом поле Result. По этим результатам можно опреде- определить, прошли ли данные проверку.
Формы и верификация данных Листинг 29.6 Проверка целостности чисел <html> <head> <title>Integer Validation*:/ title> <script languages"JavaScript"> <!—начало сценария function isInt(textObj> { var newValue = textobj . value ; var newLength = newValue. length; for (var i = 0; i != newLength; i++) aChar = newValue. substring<i,i+l) ; if (aChar < " I I aChar > "9") { return false; J ) return true ; } // конец сценария--> </script> </head> <body> <hl>Integer Validation</hl> <form name="?orml"> <input type="text" s.ize=16 maxlength=l€ name="data"> <input type="button" name="CheckButton" value="Validate" onClick="document.forml.result.value = islnt(document.forml.data)"> <br> Result <input type="text" size=16 maxlength=16 name="result"> </form> </body> </html> Строки Код в листинге 29.7 проверяет допустимость символов, вводимых в строку: это должны быть буквы и несколь- несколько других символов. Другие символы определяются переменной extraChars. Если пользователь вводит не- небуквенный символ или знак, не определенный этой переменной, функция возвращает false. Такой код мож- можно применить для верификации имен, поскольку неко- некоторые из них содержат точки, пробелы, дефисы и за- запятые . ЛИСТИНГ 29.7 Проверка строки <html> <head> <title>String Validation/title> <script language="JavaScript"> <!—начало сценария function isString(textobj) { var newValue = textObj.value; var newLength = newValue.length; |Глава 29 var extraChars=". -," ; var search; for (var i = 0; i != newLength; i++) { aChar = newValue.substring(i,i+1) ; aChar = aChar.toUpperCase () ,- search = extraChars.indexOf(aChar), .if (search = -1 && (aChar < "A" | aChar > "Z") ) ( return false; return true ; > // конец сценария—> </script> </head> <body> <hl>String Validation</hl> <form name="forml"> <input type="text" size=16 maxlength=l6 name="data"> <input type="button" name=" Che ckBu tton " value="Validate" onClick="document.forml.result.value isString(document.forml.data)"> <br> Result <input type="text" size=16 maxlength=l6 name="result"> </form> </body> </html> Денежные значения Код из листинга 29.8 использует технологию, несколь- несколько отличную от применяемой в примерах проверки строк или целочисленных значений. Вместо выполне- выполнения прямой верификации, выполняется форматирова- форматирование, а значение выводится на экран в виде денежной суммы с двумя десятичными разрядами. Это еще один пример использования объекта Text функцией с целью изменения значения объекта. Если функция не смогла преобразовать данные, представленные в виде денежной суммы, по умолчанию принимается значение 0. Листинг 29.8 Денежный формат <html> <head> <title>Money Format</title> <script language= "JavaScript"> <!--начало сценария function moneyFormat(textobj) { var newValue = textObj.value; var decftmount = "" ; var dolAmount = "" ; var decFlag = false; var aChar = "";
Избранные программные технологии Часть V // Игнорировать все, кроме целых и // десятичных чисел. for (i=0; i < newValue. length; i++) { aChar = newValue.substring(i,i+l); if(aChar >= " SS aChar <= "9") { if(decFlag) { decAmount = "" + decAmovmt + aChar; } else { dolAmount = "" + dolAmount + aChar; if(aChar = ".") { if(decFlag) { dolftmount = "v break; deeFlag=true; // Убедимся, что вместо суммы появляется // хотя бы 0. if(dolAmount = "") { dolAmount = "О"; > // Убрать ведущие нули. if(dolAmount.length > 1) { while (dolAmount. length > 1 SS dolAmount.substring@,1) = ") { dolAmount = dolAmount.substringA,dolAmount.length); // Округлить десятичное значение. if(decAmount.length > 2) { if(decAmount.substring B,3) > ") { decAmount = parselnt(decAmount.substring@,2)) + 1; if(decAmount < 10) { decAmount = " + decAmount; else { decAmount = + decAmount; else { decAmount = decAmount.substringfO,2); if (decAmount = 100) { decAmount = 0"; dolAmount = parselnt (dolAmount) + 1; J // Заполнить справа decAmount if(decAmount.length == 1) { decAmount = decAmount + "; 'l if (decAmount. length ==0) { decAmount = decAmount +¦ 0" // Проверка на наличие отрицательных // значений и сброс textobj if(newValue.substring @,1) != '-' || (dolAmount = " SS decAmount = 0")) { textobj.value = dolAmount + "." + decAmount; else( textObj. value = ' -' + dolAmount + decAmount; 1 // Конец сценария—> </script> </head> <body> <hl>Money Format</hl> <form name="forml"> <input type="text" size=16 maxlength=l6 name=" data"> <input type="button" name="CheckButton" value="Format" onClick="moneyFormat(document.forml.data)"> </form> </body> </html> Кредитные карточки Один из важнейших аспектов ведения бизнеса в Web связан с принятием заказов, оплачиваемых через кредит- кредитные карточки. С помощью JavaScript можно проверить номер кредитной карточки до того, как произойдет ее сохранение на сервере с целью конечной проверки. В листинге 29.9 показано, как можно выполнить проверку номера. Он должен соответствовать основным прави- правилам, которые были установлены компаниями, поддер- поддерживающими кредитные карточки. Если в процессе про- проверки выясняется, что был введен неправильный номер, об этом следует проинформировать пользователя и предложить ввести номер заново. Если пользователь не желает вносить изменения во введенный номер, его можно снова принять и выполнить окончательную про- проверку на серверной части, прибегнув к помощи услуг электронной коммерции. Код, представленный в листинге 29.9, можно исполь- использовать только для предварительной проверки номера кредитной карточки. Использование сервиса электрон- электронной коммерции на серверной части — единственный путь полной верификации кредитной карточки. Функция isCreditCard начинается с игнорирования введенных пользователем тире. Затем число поступает в алгоритм вычисления кода, известного как контрольная сумма. Если контрольная сумма совпадает с последней цифрой номера кредитной карточки, значит номер кар- карточки корректен. Однако даже если номер успешно про-
Формы и исрификащт данных шел проверку, это не значит, что счет существует, рав- равно как и то, что он не был закрыт. Это лишь означает, что введенный номер соответствует всем правилам. При желании получить более подробную информацию о том, как происходит подсчет контрольной суммы, ее можно найти на сайте http://www.websitfer.com/ cardtype.html. Листинг 29.9. Верификация кредитной карточки. <html> <head> <title>Credit Card Validation</ title> <script language="JavaScript"> < ! - -начало сценария function isCreditCard(textObj) { /* * Функция проверки ввода номера кредитной * карточки. * В случае корректности контрольной сунны * функция возвращает true. */ var ccNum; var odd = 1; var even = 2; var calcCard = 0; var calcs = 0; var ccNum2 = " " ; var aChar = ' ' ; var cc ; var r; .ccNum = textob j . value ; for (var i = 0; i != ccNum. length; i++) ( aChar = ccNum.substring(i,i iffaChar = '-'> { continue ,* I ссНшл2 = ccHum2 + aChar; cc = parselnt (ccNum2) ; if(cc == 0) { return false; r = ccNum. length / 2 ; if(ccNum.length - (parselnt(r)*2) =0) { odd = 2; even = 1 ; J for (var x = ccNum. length - 1; x > 0; x — ) r = x / 2; if(r < 1) { f if(x - (parselnt(r) * 2) != 0) { calcs = (parselnt(ccNum.charAt(x - 1») * odd; else { Глава 29 calcs = (parselnt(ccNum.charAtfx - 1))) * even; if(calcs >= 10) { calcs = calcs - 10 + 1; calcCard calcCard + calcs; calcs = 10 - (calcCard % 10) ; if (calcs = 10) { calcs = 0 ; if (calcs = (parseInt(ccNum.charAt(ccNum. length - 1)))) return true ; } else { return false; // конец сценария—> </script> </head> <BODY> <hl>Credit Card Validation</hl> <form name="forml"> <input type="text" size=16 maxlength=l6 name="data"> <input type="button" name="Che ckButton" value="Validate" onClick="document.forral.result.value isCreditCard(document.forml.data)"> <br> Result <input type="text" size=16 maxlength=16 name="result"> </form>' </body> </html> Пример: тестер цветов JavaScript В следующем примере, показанном на рис. 29.9, исполь- используются описанные в главе возможности внедрения тес- тестера цветов. Одной из важнейших задач разработки HTML-формы является выбор цветов фона и символов, что обеспечит эстетическое наслаждение и четкость. Многие комбинации соответствуют этим критериям, а многие — нет. Тестер цветов JavaScript позволяет выби- выбирать два цвета и просматривать в отдельном окне, как выглядит эта комбинация. В окне содержится HTML- код для спецификации комбинации цветов. Пользова- Пользователь может вырезать и вставить это определение прямо в HTML-код.
Избранные программные технологии Color Checker Text Color: Red: |'J Green: |o Blue: jo Background Color: . Red:|?5 ^ Blue: B5 wmmwmmm Sample Text Use: <bodybgco!or-"#?HOB" tBtt-"#O0000O":> Text Color=(l BackgroundC6lor=B3J,255,255) I Using the Color Checker The Color Display Checker is a utility that I allows you to display a user selected text I color against a user selected bat ' color. Colors rue entered as GRB triplets: a set of and blue values that comprise the color. Each value can range from 0 to 255. Colors arc selected for a color and for a NkI color. РИСУНОК 29.9. Проверочное устройство цвета. Определение значений цветов происходит с исполь- использованием триплетов RGB (красный-зеленый-синий). Этот триплет содержит три значения, представляющие красную, зеленую и синюю составляющие цвета. Упо- Упомянутые значения лежат в диапазоне от 0 до 255. На- Например, триплет B55,0,0) представляет чистый красный цвет. В табл. 29.2 перечислены некоторые RGB-значе- RGB-значения цветов. Таблица 29.2 RGB значения цветов RGB значение Цвет @,0,0) B55,0,0) B55,255,0) B55,0,255) @,255,0) @,255,255) @,0,255) A28,128,128) B00,200,200) B55,255,255). Черный Красный Желтый Ярко-красный Зеленый Голубой СИНИЙ1 Темно-серый Светло-серый Белый Так же как и в интерактивных формах, все процес- процессы проходят на стороне клиента. Программа определяет конструктор для объекта Color, в котором содержится RGB-триплет. Объекты Color имеют метод setColor(), который устанавливает RGB-триплет и вычисляет его эквивалент в виде шестнадцатиричных значений, кото- которая применяется для установки цвета в HTML-дескрип- HTML-дескрипторе <body>. В программе используется два экземпля- экземпляра объекта Color: один — для цвета символов, другой — для цвета фона. Обработчик событий onBlur вызывает программу, выполняющую проверку (validateRGBQ) каждый раз, когда одно из шести текстовых по «ей вво- ввода теряет фокус. Хотя форма не имеет кнопки Submit, у нее есть объект Button с именем Submit. Метод onClick обраща- обращается к функции processForm(), которая и вносит изме- изменения. Она создает окно для вывода, которое распола- располагается отдельно от программы тестера цветов. Ссылка на окно производится через popWin. Функция processForm() проверяет, равно ли popWin значению null. Если это так, processForm() с использованием ме- метода Windopen() создает отдельное окно Color Sample. Далее все происходит несколько запутанно. Пользо- Пользователь может закрыть окно Color Sample. Единственный способ определить, что произошло заключается в про- проверке значения popWin.document. Если значение popWin является null, тогда значение popWin.document — null, из чего следует, что окно Color Sample было закрыто. В данном случае потребуется воссоздать окно Color Sample. Функция processForm() вызывает функцию <JoSample(), которая генерирует содержимое окна Color Sample. В дескрипторе <body> мож:но заметить экземпляр обработчика событий onUnload, который вызывается каждый раз, когда происходит закрытие окна. Он обра- обращается к функции closePopWin(), закрывающей окна Color Sample и Help, если они существуют. Обратите внимание на кнопку с именем HelpButton. Когда пользо- пользователь щелкает на этой кнопке, программа создает но- новое окно со справочной информацией. В листинге 29.10 показан полный исходный код для инструментального средства Color Checker. Листинг 29.10. Инструментальное средство Color Checker. <html> <head> <title>Color Checker</title> <script language="JavaScript "> - начало сценария // Конструктор для объектов цветов function color(r,g,b) { this.setColor = setColor,- this.setColor(r,g,b); // Метод установки цветов объектов function setColor(r,g,b){ this.red = r ; i = g/ this.blue = b; this.hex = rgb2hex(r,g,b); // Преобразование RGB-триплета в строку с // шестнадцатиричными значениями function rgb2hex(r,g,b){ var str = '"#' + num2hex(r) + г num2hex +
Формы и верификация данных return(str)t 11 // Преобразование цифровой строки в // шестнадцатиричную function num2hex(n){ var str = "";. var hexstring = 123456789abcdef'¦ ; while (true) { digit = hexstring.substring( (n%16>, ( str = digit +¦ str; n = n » 4 ; if (n шш 0) break; // Заполнение строки, если необходимо if (str.length < 2) { str = '0' + str; } return(str); // Проверка значешй компонентов RGB function validateRGB(textObj) { var str = textObj .value; if (str. length =0) { userAlert(textObj) ; .return false ; 1 for (var i = 0; i < str. length; ++i) { var ch = str.charAt(i) ; if (ch<"O" I I ch>'9') { userAlert(textObj); return false; 1 i var value = parselnt (str,10) ; if (value < 0 I I value > 255) ( userAlert(textObj) ; return false; ") else { return true; J // Предупреждение пользователя об оиибке ввода function userAlert (textObj) { alert("Please enter a value between 0 and ^255."); textObj .focus () ; textObj , select( ) ; i // Запись фрейма для отображения примера functi ondoSample (doc, tc, be ) { var mytext—"<hl>Sample Text</hl>" ; doe.open<); doc . write ( "<htmlXheadXtitle>ColorSample</ titlex/head>") ; doe.write{'<body bgcolor=' + be. hex + ' text=' + tc.hex + ¦>'); doc.write (mytext) ; doc .write('Use: Slt;:body bgcolor=' + be. hex 1 text='+ tc.hex + 'Sgt;1); Глава 29 doc.write("<br>Text Color=(",tc.red, ",",tc.green,", ^tc.blue,") "); doc.write("<br>Background Color=(",be.red,",",bc.green,",",be.blue,")"); doc.write("</bodyx/html>") ; doc.close (); I // Обработка переданной формы function processForm(myform) { var winFeatures = "scrollbars,width=400,height=250"; if ( (validateRGB (my form, redtxt) SS validateRGB (rryf oral, grntxt) SS validateRGB (myform, blutxt) SS validateRGB (myform, redbg) validateRGB (myform . grnbg) & & validateRGB(myform.blubg) ) = false) { return false; ) var textColor = new color (myform. redtxt. value , myform. grntxt. value , my form, blutxt .value) ; var backColor = new color (myform. redbg. value , my form, grnbg, value , myform.blubg.value); ¦if (popWin =^ null) popWin = window, open ("", "PopWindow",winFeatures) ; else { if (popWin. document = null) { popWin — window.open( " ", "PopWindow",winFeatures) ; doSample (popWin. document, textColor, backColor ) popWin . focus ( ) ,' return true; I // Установка начальных значений формы function resetForm(myform) { my form. redtxt . value = 0 ; myf orm . grntxt . value = 0 ; myf orm. blutxt. value = 0; myform. redbg . value = 255; my form . grnbg . value = 255; myf orm . blubg . value = 255; processForm(myform) ; // Предложение ввести корректные значения function setPrompt() { window. status="Please enter a value between and 255."; return true ; // Закрыть всплываюиие окна functionclosePopWin( ) { if (popWin != null ss popWin . document ! = null) popWin . close ( ) ; if (helpWin != null SS helpWin . document ! — null) helpWin. close(); I
Избранные программные технологии Часть V / / Очистка строки function clear Prompt () { window.status=""; return true ; //Вывод страницы со справочной информацией function displayHelp() { var winFeatures = "scrollbars,width=400,height=250"; if (helpWin == null) helpWin = window, open ("", "HelpWindow", winFeatures) ; ¦else if (helpWin. document = null) helpWin = window, open ("", "HelpWindow", winFeatures) ; helpWin.document.open() ; helpWin . document .write ( "<htmlXheadXtitle>Color ^Checker Help </titleX/head>") ; helpWin . document . write ( "<body ^»bgcolor=fff f ff>") ; helpWin.document.write ("<hl>ColorChecker helpWin. document. wri te ("<h2>Using the Color helpWin. document, write ("The Color Display ^Checker is a utility that "); helpWin. document, write ("allows you to display ^a user selected text ") ; helpWin. document, write ("color against a user w selected background color. ") ; helpWin. document, write ("Colors are entered as '-'RGB triplets: a set of ") ; helpWin. document.write ("red, green, and blue ^•values that comprise the ") ; helpWin. document, write ("color. Each value wcan range from 0 to 255. "> ; helpWin. document, write ("Colors are selected ^for a background color ") ; helpWin. document, write ("and for a text ^color. " ) ; helpWin . document. write ( "</bodyX/html>") ; helpWin.document.close() ; helpWin.focus() ; return true ; // Инициализация var popWin = null ; var helpWin = null; // Конец сценария —> </script> </head> <body bgcolor="#ffffff " text="#000000" onUnload="closePopWin()"> <hl>Color Checker</hl> <form name="myform"> <h2>Text Color:</h2> Red: <input type="text" size=3 maxlength=3 name="redtxt" value=" onChange="validateRGB(this)" onPocus="setPrompt ()" >onBlur="clearPrompt()"> Green: <input type="text" size=3 maxlength=3 name="grntxt" value=" onChange="validateRGB(this)" onFocus="setPrompt() " onBlur="clearPrompt () "> Blue: <input type="text" size=3 max1engt h= 3 name="blutxt" value=" onChange="validateR6B(this)" onFocus="setPrompt()" onBlur="clearPrompt ()"> <h2>Background Color:</h2> Red: <input type="text" size=3 maxlength=3 name="redbg" value=55" onChange="validateRGB(this)" onFocus="setPrompt()" onBlur="clearPrompt()"> ¦Green: <input type="text" size=3 maxlength=3 name= " grnbg " value=55" onChange="validateRGB(this)" onFocus="setPrompt()" onBlur="clearPrompt ()"> Blue: <input type="text" size=3 maxlength=3 name="blubg" value=5S" onChange="validateRGB(this)" onFocus="setPrompt()" onBlur="clearPrompt()"> <brxbr> <input type="button" value="Submit" onClick="processForm (document.myform) "> <input type="reset" value="Clear" onClick="resetForm(document.myform)"> <input type="button" value="Help" name= " HelpBu tton " onClick="displayHelp()"> </form> </body> </html> Резюме В JavaScript существенно усовершенствованы базовые возможности HTML-формы. Если используется JavaScript, то большинство процессов, выполняемых на строке сер- сервера, могут проходить на клиентской части. Возможно- Возможности делятся на следующие группы::
Формы иверификацияданных Обратная связь с пользователем. JavaScript позволя- позволяет обеспечивать обратную связь с пользователями за счет комбинации обработчиков событий и управле- управления содержимым панели состояния браузера. Окна сообщений. С помощью окон предупреждений и диалоговых окон можно передавать пользователю сообщения, запрашивать подтверждения запроса и обеспечивать дополнительную информацию перед отправкой форм. Верификация данных, введенных пользователем. Можно проверять поля ввода, группы полей и всю фор- форму через обработчики событий и функции JavaScript. Пользователи могут получать информацию обратной связи в контексте текущей формы (т.е. страница не Глава 29 заменяется новой страницей с сообщением об ошиб- ошибке). • Можно создавать интерактивные формы, в которых часть процессов, а может быть и все, выполняются на стороне клиента. JavaScript несложно задействовать для создания форм, более простых в использовании и менее подверженных к ошибкам. В свою очередь, можно создавать формы, обеспечивающие более быстрый ответ, нежели сервер- но-ориентированные программы, в особенности если пользовательская связь с сервером имеет низкую про- пропускную способность. 13 !
Персонализация и динамические страницы В ЭТОЙ ГЛАВЕ Статические Web-страницы • Немного о cookie-наборах • Использование cookie-наборов • Серверы и браузеры, поддерживающие механизм cookie-наборов • Другие способы поддержки информации о состоянии Путешествуя по Internet, многие замечали, что в сайты помещается все больший и больший объем информации, которая охватывает практически все необходимые темы и удовлетворяет многие запросы. Дабы оградить пользо- пользователей от необходимости чтения ненужной информа- информацией, сайты персонализируют, что, в свою очередь, по- помогает направить информацию в определенное русло. Web-сайт знает, что данный пользователь желает про- просматривать страницы, посвященные только спорту или курсу акций. На сегодняшний день Web-страницы — это и друг, и финансовый советчик в одном лице. Времена замороженных статических Web-страниц давно прошли. Наступило время динамических Web-страниц! Когда пользователь посещает любимый онлайновый книжный магазин, ему предоставляется не просто спи- список книг, но предлагается литература, которая может удовлетворить его запросы, базируясь при этом на пре- предыдущих покупках пользователя. Многие онлайновые магазины и порталы используют массивные серверные базы данных, отслеживая личные предпочтения и це- цепочки покупок. Все это ускоряет процесс персонализа- ции и способствует проявлению динамических свойств. Тем не менее, разработчик Web-страниц с использова- использованием JavaScript может наделить Web-сайт большей при- привлекательностью и дружественностью по отношению к посетителям. В этой главе рассматриваются способы управления cookie-наборами, параметрами строки запроса URL и скрытыми переменными формы с помощью JavaScript, призванные обеспечить персонализацию и динамичес- динамический характер страницы. Перед тем как приступить к созданию динамических страниц, стоит разобраться, почему Web-страницы по своей природе являются ста- статическими. Статические Web-страницы Web-серверы обладают памятью относительно неболь- небольшой емкости. При получении запроса на страницу сер- сервер не знает точно, кто вы такой и что вводилось в фор- форму три страницы назад. Он также не знает, является ли посещение пользователя первым или, скажем, семьде- семьдесят пятым. Одной из проблем использования Hypertext Transfer Protocol (HTTP) является то, что этот протокол не отслеживает состояние взаимодействия с сервером. Под состоянием понимается информация о посещениях Web-сайтов пользователем. Оно поддерживается по мере передвижения по страницам Web-сайта. Состояние мо- может использоваться Web-сервером или программой JavaScript (либо обоими), чтобы подстроить под сайт все проделанные действия. С помощью такой информа- информации можно устанавливать приоритеты, значения фор- формы по умолчанию, подсчитывать количество визитов и многое другое, что может существенно упростить поиск и просмотр информации в Web. Существует множество способов поддержки инфор- информации о состоянии: Сохранение ее в cookie-наборах. Кодирование ее в ссылке URL. Отправка ее в форме скрытых переменных. Сохранение ее в переменных других фреймов. Сохранение ее в Web-сервере Существует много других проблем, связанных с под- поддержкой информации о состоянии. Во время просмот- просмотра сайта пользователь может перейти к другому Web-сай- Web-сайту и возвратить минуты, часы, дни, чтобы выяснить, что любая сохраненная информация не зависит от даты или
Персонвлизсщия и динамические страницы Существует много других проблем, связанных с под- поддержкой информации о состоянии. Во время просмот- просмотра сайта пользователь может перейти к другому Web-сай- Web-сайту и возвратить минуты, часы, дни, чтобы выяснить, что любая сохраненная информация не зависит от даты или же не была уничтожена. Можно вернуться, нажав кнопку Back, при помощи закладки или же просто сделать так, чтобы закодированная информация URL была перепи- переписана или потеряна. Web-разработчик должен поддерживать информа- информацию о состоянии независимо от того, как пользователь перемещается по сайту: с помощью кнопок формы или же URL-ссылок на странице. Это означает, что инфор- информация добавляется и в скрытые переменные формы, и в каждый дескриптор <а href...> на странице. Учитывая все эти трудности, неплохо, чтобы меха- механизмы поддержки были более удобными в применении., К счастью, это так и есть. Существует много преиму- преимуществ поддержки состояния, они проявляются и при однократном посещении сайта, и при переходе от од- одного сайта кдругому. Примите во внимание следующий сценарий: • Приложения потребительских корзинок. Пользова- Пользователь просматривает сайт, выбирая определенные пун- пункты и перенося их в виртуальную корзину. В любое время пользователь может просматривать пункты в данной корзине, изменять ее состав, проводить ее проверку, а после уже производить покупку. Отсле- Отслеживание информации о том, какие пользователи ка- какими корзинами владеют — весьма важная задача. ¦• Персонализированные порталы. Многие Web-сайты обеспечивают порталы, где пользователь может под- подстраивать под себя все, что видит. После выбора пользователем размещения, схемы цветов, установоч- установочных параметров, предпочтения сохраняются в пользо- пользовательском компьютере через механизм cookie-наборов. В любой момент пользователь может вернуться к сайту и получить ранее сконфигурированную им страницу. • Премии за частые посещения. Сохраняя информа- информацию на клиентском компьютере, приложение может проследить, сколько раз браузер обращался к данной странице. Если количество посещений достигает оп- определенного количества, пользователь получает до- доступ к службам более высокого уровня, либо же уве- увеличится количество этих служб. • Изменение баннеров. Каждый раз когда пользователь посещает страницу, необходимо изменять графические баннеры. Этот способ обычно применяется для перио- периодического просматривания рекламных объявлений. Закладки. Проверьте, где находился пользователь в последний раз посещения сайта. Читал ли он рассказ, Глава 30 заполнял ли анкету или играл в игру? Пусть он нач- начнет с того места, где остановился. ¦• Игры. Запомните текущее или максимальное количе- количество очков. Предоставьте новые задачи, основанные на прошлых действиях и ответах. Немного о cookie-наборах ¦Cookie-наборы позволяют хранить информацию на кли- клиентском компьютере для дальнейшего ее восстановления. Несмотря на то что с ними связаны определенные не- недостатки, все же cookie-наборы — это мощная техно- технология поддержки состояния со стороны клиента. Компания Netscape переняла начальную спецификацию cookie-наборов. Несмотря на то что наборы называ- называются cookie — это не основная причина того, почему было выбрано именно это имя. Страница специфика- спецификаций cookie-наборов признает, что "объект состояния назван cookie не по причине принуждения". Cookie-наборы хранят данные в виде пары name=value (имя=зиачение). Можно выбрать любое имя и комбина- комбинацию значений. Очень выгодное свойство cookie-набора связано с возможностью установки даты завершения действия, а также того, какие страницы могут просмат- просматривать cookit-информацию. Преимущества cookie-наборов Одним из основных свойств cookie-набора является их устойчивость. Когда восприятие cookie-наборов уста- установлено на пользовательском браузере, эти наборы мо- могут храниться на протяжении многих дней, месяцев и даже лет. Именно это и упрощает процесс сохранения информации о последних посещениях и о предпочте- предпочтениях пользователя. То же свойство обеспечивает доступ к cookie-наборам каждый раз, когда пользователь воз- возвращается на страницу. Эффективность cookie-наборов особенно повышает- повышается в при работе с JavaScript. С момента появления в JavaScript функций чтения, добавления и редактирова- редактирования cookie-наборов, программы JavaScript могут исполь- использовать cookie-наборы для хранения информации о пользователе и его маршруте по Web-сайту. Ограничения и недостатки cookie-наборов Некоторые ограничения могут показаться весьма про- проблематичными. Обычно cookie-наборы хранятся на пользовательском компьютере в специальном файле cookie. Так же, как и другие файлы, его можно удалить по случайности или с определенной целью, что унич- уничтожит всю хранящуюся в нем информацию. Файл cookie можно защитить от записи. Программные средства бра-
Избранные программные технологии Часть V узера могут накладывать ограничения на размер или количество сохраняемых cookie-наборов. Новые cookie- наборы могут перезаписывать информацию в старых наборах. Cookie-наборы связаны с одним определенным ви- видом браузера, поэтому когда пользователь переходит с одного браузера на другой, могут возникать проблемы. Если коллекция cookie-наборов получена в результате работы в браузере Netscape Navigator, то при переходе к Microsoft Internet Explorer доступ к cookie-наборам будет утерян. И наконец, если несколько людей используют один и тот же компьютер и браузер, они смогут найти себя при помощи cookie-наборов, принадлежащих кому-ни- кому-нибудь другому. Причина связана с хранением cookie-ин- cookie-информации в файле и браузер не может найти отличия между различными пользователями. Кроме того, существуют проблемы относительно ис- использования cookie-наборов. Многие браузеры хранят cookie-информацию в незашифрованном текстовом фай- файле. Конфиденциальная информация, такая как пароли, в cookie-файле храниться не должна. В противном слу- случае, любой, кто получает доступ к компьютеру, сможет ее прочесть. Некоторые Web-брузеры обладают возможностью предупреждения пользователя, когда предпринимается попытка установки cookie-набора. Браузер можно скон- сконфигурировать таким образом, чтобы cookie-наборы во- вообще не устанавливались. Иногда это приводит к нераз- неразберихе на пользовательской части, когда диалоговое ¦окно сообщает о том, что производятся определенные действия над каким-то "cookie". Но если механизм cookie-наборов заблокирован, то тщательно разработан- разработанные Web-приложения вообще не будут запускаться. Нельзя установить неограниченное количество cookie-наборов для каждого Web-браузера, посещающе- посещающего сайт. Ниже показаны возможные количество и раз- размеры cookie-наборов: • Количество cookie-наборов на один сервер или домен: 20 • Общее количество cookie-наборов на браузер: 300 Размер самого большого cookie-набора: 4 Кбайт (включая оба параметра name и value) Если эти пределы превышаются, браузер может по- попытаться избавиться от старых cookie-наборов, отбрасы- отбрасывая в первую очередь более давно используемые cookie- наборы. Мифы о cookie-наборах Самая большая проблема в данном случае имеет психо- психологические корни. Некоторые пользователи считают, что cookie-наборы — инструмент, используемый "старшим братом" для раскрытия важнейших секретов. Может быть, это несколько преувеличиваю, cookie-наборы от- отвечают за хранение информации о страницах, по- посещаемых пользователем, о количестве посещений, о просмотренных рекламных баннерах, о том, что было выбрано и введено в форму. Именно поэтому многие ду- думают, что нарушается их право на конфиденциальность, когда cookie-наборы попадают в компьютер. В действительности, cookie-наборы очень редко ис- используются с такой целью. Теоретически это возможно, но на сегодняшний день существует много других, бо- более простых и доступных способов получения конфи- конфиденциальной информации. Хотя подобного рода мыс- мысли могут и не покинуть читателя прямо сейчас, однако они уже не должны касаться cookie-наборов. Другие пользователи жалуются на то, что лишняя информация занимает много места на жестком диске. Это довольно-таки веское основание. Программные средства браузера ограничивают общий объем cookie- файла до 1.2 Мбайт, причем на один сайт приходится не более 80 Кбайт. Отметим, что это число мало по сравнению с размерами страниц и графических изобра- изображений, которые Web-браузер хранит в страничном кэше. Третья группа пользователей уверена, что если cookie- набор был установлен на одном сайте, то его можно будет прочесть с других сайтов. Это полностью невер- неверно. Программные средства Web-браузера перекрывают доступ к cookie-набору другого сайта, не участвовавше- участвовавшего в его создании. Если пользователи понимают всю пользу примене- применения cokie-наборов, все эти слухи ни к чему не приве- приведут. Компания Netscape переняла начальную спецификацию cookie-набора. Более подробную информацию можно найти на Web-сайте компании Netscape по адресу http:// www.netscape.com/newsref/std/cookie_spec.html. Использование cookie-наборов До этого момента были рассмотрены все за и против cookie-наборов и выяснено, что cookie-наборы — это именно то, что необходимо для создания полноценно- полноценного Web-приложения. В этом разделе исследуются фун- функции, необходимые для чтения и установки cookie-на- cookie-наборов, что окажет помощь в создании динамических Web-сайтов, а также их персонализации. В разделе так- также рассказано, как найти справочную информацию о cookie-наборах.
Лерсонализация и динамические страницы Получение значений cookie-наборов Имена и значения cookie-наборов хранятся и устанав- устанавливаются при помощи свойства cookie объекта Document. Для сохранения неформатированной строки cookie в переменной потребуется воспользоваться следующей командой: var myCookie=document, cookie Для отображения ее на Web-странице применяется следующая команда: document.write ("Raw Cookies: " + document.cookie + "<br>") ,• JavaScript сохраняет cookie-наборы в следующем форм; те: namel=valuel; name2=value2; name3=value3 Отдельные пары name=value разделяются точкой с запятой или пробелом. После последнего значения точ- точка с запятой не ставится. Процесс вывода cookie-набо- cookie-наборов упрощается за счет использования программы, представленной в листинге 30.1. Листинг 30.1 Функция GetCookie function GetCookie (name) { var result = null; var myCookie = " " + document, cookie + ";"; var searchName = " " + name + "=" ; var startOfCookie = myCookie.indexOf(searchName); var endOfCookie; if (startOfCookie != -1) { startOfCookie += searchName.length; // пропустить последнее имя cookie endOfCookie = myCookie.indexOf (";", startOfCookie); result = unescape(myCookie.substring(startOfCookie, endOfCookie)); i ret.urn result; В листинге ЗОЛ строка myCookie помогает избежать граничных условий; при этом следует убедиться, что все строковые имена cookie-наборов начинаются с пробе- пробела, а заканчиваются точкой с запятой. Таким образом, будет несложно отыскать начало части строки name=, Пропустить ее и вывести все, что находится между точ- точкой и следующей точкой с запятой. Установка значений cookie-наборов В комбинации name=value находится минимальный объем информации, необходимой для установки cookie- набора. Однако, имеется есть еще кое-что, необходимое для cookie. Ниже представлен полный список парамет- параметров, применяемый для спецификации cookie-набора: Глава 30 ¦ • name=value expires=date • path=path ¦ • domain=domainname secure Имена и значения cookie Name и value могут быть чем угодно. Иногда они быва- бывают пояснением, таким как FavoriteColor=Blue, Зачастую это код, интерпретируемый программой JavaScript, напри- например: CurStat=l:2:l:0:0:l:0:3:1:1. Самая простая форма для установки cookie-набора выглядит следующим образом: function SetCookieEZ (name, value) { document. cookie = name + "=" + escape (value) ; ) Обратите внимание, что значение кодируется с по- помощью функции escape(). Ели бы в строке была точка с запятой, это могло бы уберечь от неожиданных по- последствий. Функция escape() избавляет нас от подобного рода проблем. Кроме того, обратите внимание, что действия свой- свойства document.cookie отличаются от действий других свойств. В большинстве случаев применение оператора присваивания (=) приводит к полному переписыванию существующего свойства с новым значением. Но это все не относится к свойству cookie. Здесь любое новое при- присваиваемое имя (пате) добавляется в активный список cookie-наборов. Если данное имя присваивается дважды, первое присваивание заменяется вторым. Однако, существуют и исключения, которые рас- рассматриваются в разделе, посвященном path. Дата истечения Параметр expires=date сообщает браузеру о времени существования cookie-набора. Страница спецификации cookie-наборов на сайте Netscape устанавливает следу- следующую форму дат: Wdy, DD-Mon-YY HH:MM:SS GMT Например: Mon, 08-Jul-96 03:18:20 GMT Этот формат основан на Internet RFC 822, о котором можно узнать по адресу: http://www.w3.org/hypertext/ WWW/Protcols/rfc822/#z28. Единственное различие между RFC 822 и реализа- реализацией Netscape заключатся в том, что дата истечения дол- должна завершаться GMT (Greenwich Mean Time). К счастью, язык JavaScript обеспечивает такую работу функции. Используя функцию toGMTString(), можно установить срок истечения действия cookie-набора в ближайшем или далеком будущем.
Избранные программные технологии Несмотря на то что функция toGMTStringl) не соот- соответствует спецификации Netscape, все же она рабо- работает В JavaScrip-f. Если дата истечения не определена, cookie-набор остается в действии, пока браузер не будет закрыт. Сле- Следующий фрагмент кода устанавливает дату истечения cookie-набора через неделю. var name="foo"," ¦var value="bar" ; var oneWeek = 7 * 24 * 60 * 60 * 1000; var expDate = new Date () ; expDate.setTime (expDate.getTime() + oneWeek); document.cookie = name + "=" + escape(value) + "; expires=" + expDate. toGMTStringO; path По умолчанию cookie-наборы доступны и другим Web- страницам внутри того же каталога, что и страница, в которой они были созданы. Параметр ath открывает доступ к cookie-набору из других каталогов. Если зна- значение параметра path — это подстрока URL страницы, то создаваемые с параметром path cookie-набора дос- доступны на этой странице. Например, cookie-наборы мож- можно создать с помощью следующей команды: document.cookie="foo=barl; path=/javascript" ; Таким образом, cookie-набор foo доступен на каж- каждой странице в каталоге javascript и его подкаталогах. Если команда выглядит следующим образом: document.cookie="foo=bar2; path=/javascript/sam"; TO cookie-набор будет доступен страницам в каталоге /javascript/sam, но не будет доступен страницам в ка- каталоге /javascript. И наконец, чтобы сделать cookie-набор доступным каждой странице на всем сервере, воспользуйтесь сле- следующей командой: document.cookie="foo=bar3; path=/"; а что же произойдет, если в браузере много cookie-на- cookie-наборов для различных путей, а имена наборов одинако- одинаковы? Какое из них победит? В действительности, сильнейшими окажутся все. В данном случае, лучше иметь несколько cookie-наборов с одинаковыми именами, но различными значениями. Например, если страница выдает все команды, перечис- перечисленные ранее, тогда строка cookie будет выглядеть следующим образом: ?оо=ЬагЗ ; f oo=bar2 ,- f oo=barl Чтобы разобраться в ситуации, можно написать про- программу для подсчета количества значений cookie-набо- cookie-наборов, связанных с именами, как показано в листинге 30.2. Листинг 30.2 Функция GetCookieCount function GetCookieCount (name) { var result = 0 ; var myCookie = " " + document.cookie + ";"; var searchName = " " + name + "="; var nameLength = searchName.length; var startOfCookie = myCookie.indexOf(searchName); while (startOfCookie != -1) { result += 1; startOfCookie = myCookie.indexOf(searchName, startOfCookie + nameLength); } return result; И конечно же, если существует функция GetCookieCount, то должна быть и функция GetCookieNum, какая бы выводила отдельную часть cookie-набора. Эта функция выглядит так, как показано в листинге 30.3. Листинг 30.3 Функция GetCookieNum function GetCookieNum (name, cookieNum) { var result = null; .if (cookieNum >= 1) { var myCookie = " " + document, cookie + ";"; var searchName = " " + name + "="; var nameDength = searchName. length; var startOfCookie = myCookie.indexOf(searchName); var cntr = 0; for (cntr = 1; cntr < cookieNum; cntr++) startOfCookie = myCookie.indexOf(searchName, startOfCookie + nameLength); if (startOfCookie != -1) { startOfCookie += nameDength; // пропустить // последаее имя cookie var endofCookie = myCookie.indexOf(" ;" , startOfCookie); result = unescape(myCookie.substring(startOfCookie, endOfCookie)); return result; Для уничтожения cookie-набора необходимо, чтобы имя и путь совпадали с первоначально установленны- установленными исходными именем и путем. domain После того как страница на определенном сервере со- создает cookie-набор, он становится доступным для стра- страниц только на этом сервере. Поскольку параметр path обеспечивает доступ к cookie-набору за пределами ис- исходного пути, то параметр domain гарантирует доступ к другим Web-серверам на данном сайте.
Персонализйция и динамические страницы Можно сгенерировать такой cookie-набор, чтобы все пользователи, посещающие Internet, смогли его увидеть. Разработчик может только установить путь внутри до- домена. Это происходит так, поскольку применение па- параметра domain предусматривает использование, как минимум, двух периодов, если ваш домен завершается на .com, .edu, .net, .org, .gov, .mil, .int (например, .mydomain.com). В противном случае должно присут- присутствовать хотя бы три точки (.mydomain.ma.us). Строко- Строковый параметр domain должен совпадать с окончанием жмени вашего сервера. secure Последний параметр cookie-набора сообщает браузеру о том, что данный набор должен отправляться только при условии безопасного соединения с Web-сервером. Это означает то, что сервер и браузер должны поддер- поддерживать безопасность уровня HTTPS. (HTTPS — прото- протокол передачи через Internet зашифрованной информа- информации.) Если параметр secure отсутствует, это значит, что cookie-наборы передаются по сети в незашифрованном виде. А сейчас, когда изучены все параметры cookie-набо- cookie-набора, можно записать подпрограмму на JavaScript, в ко- которой бы задействовались все параметры (см. листинг 30.4). Для использования этой подпрограммы ее необхо- необходимо вызвать с любыми параметрами, которые требу- требуется установить, и со значениями null для параметров, которые не принимаются во внимание. Удаление cookie Для удаления cookie-набора необходимо установить дату истечения где-то в прошлом (насколь далеко в прошлое, значения не имеет). Дабы подстраховаться, работа дол- должна продолжаться несколько дней. В листинге 30.5 пред- представлена программа ClearCookie, используемая для уда- удаления cookie-наборов. При удалении cookie-набора не имеет значения, ка- какое использовалось значение. Подойдет любое значение. Листинг 30.4 Функция SetCookie Глава 30 ПРЕДУПРЕЖДЕНИЕ Некоторые версии Netscape некорректно преобразу- преобразуют время в GMT. Стандартные функции JavaScript для удаления cookie-наборов предусматривают то, что про- прошлый период отстает на несколько миллисекунд до те- текущего времени. Это действительно так, тем не ме- менее, данный принцип не действует на всех платформах. Для подстраховки стоит выбрать дату на несколько дней уходящую в прошлое. Пример применения cookie-набора В листинге 30.6 приводится программа на JavaScript, демонстрирующая использование cookie-наборов. Эта программа позволяет пользователям создавать персона- персонализированные страницы "новости дня", содержащие ссылки на сайты с общей информацией и определен- определенным количеством различных категорий. Предпочитае- Предпочитаемые ссылки пользователя хранятся в cookie-наборах. На рис. 30.1 показано, как выглядит страница Favorites. ПРЕДУПРЕЖДЕНИЕ В 1Е3.0 свойство cookie работает, только если стра- страницы, использующие свойство cookie, получены из Web-сервера. :: :¦ д»гдгтал.*уг^татдтлщ Your Favorites: :";VmwAi! j :_-¦'_-¦ Sett-f ¦ notes1"' Comics Qitettt General News Auctions ebay This is avery dull page unless youhave a JavaScript embledbrowser. ?1 РИСУНОК 30.1 Страница Favorites function SetCookie (name, value, expires, vai:' expstring = ((expires = null) ? ' var pathString = ((path = null) ? "" var domainstring = ((domain = = null) ? var securestring = ((secure == true) ? document, cookie = name + "=" + escape secureString; path, domain, secure) { ' : ("; expires=" + expires. toGMTString ())) ; : <"; path=" + path)); : ("; domain=" + domain) ) ; secure" : (value) + expstring + pathString + domains tring +
Избранные программные технологии Часть V Листинг 30.5 Функция ClearCookie function ClearCookie (name) { var ThreeDays = 3 * 24 * 60 * 60 * 1000; var expDate = new Date () ; expDate.setTime (expDate. getTime () ThreeDays); document.cookie = name + "=ImOutOfHere; expires=" + expDate.toGMTString(); ЛистингЗО.6 Сценарий Favourite_ <htna> <head> <script language="JavaScript"> <!— Comment out script from browsers that don't know JavaScript / / ===================== =====: // Стандартные подпрограммы работы с cookie-наборами // GetCookie - GetCookie возвращает Значение определенного cookie-набор или null, // если cookie-набор не существует function GetCookie (name) С var result = null; var myCookie = " " + document. cookie + " ,• " ; var searchName = " " + name + "=" ; var startOfCookie = myCookie. indexOf (searchName) ; var endOf Cookie ; if (startOfCookie != -1) 1 StartOf Cookie += searchName . length ; // пропустить последнее имя cookie-набора endOfCookie = myCookie. indexOf (" ;" , startOfCookie) ; result unescape (myCookie. substring (startOfCookie , endOf Cookie) ) ; "') return result; } //- —¦ // SetCookieEz - SetCookieEz быстро устанавливает cookie-набор, который будет // действовать вплоть до закрытия браузера. function SetCookieEz (name, value) { document . cookie = name + "=" + escape (value) ; // SetCookie - SetCookie добавляет или заменяет cookie-набор. Null используется / / для параметров , не имеющих значений. function SetCookie (name, value, expires, path, domain, secure) С var expString = ((expires == null)? "" : ("; expires=" + expires. toGMTString ())); var pathString = ((path = null) ? "" : ("; path=" + path)); var domainString = ((domain == null)? "" : ("; domain=" + domain)); var secureString = ((secure = true) ? " ; secure" : "") ; document . cookie = name + "=" + escape (value) + expString + pathString + domainString+ secureString; } II—т // ClearCookie - ClearCookie удаляет cookie-набор за счет установки даты истечения — // трех дней в прошлом function ClearCookie (name)
Персоналюация и динамические страницы Глава 30 var ThreeDays = 3*24* 60* 60* 1000; var expDate = new Date ( ) ; expDate . setTime (expDate.getTime() ThreeDays); document, cookie = name + "=ImOutOf Here ; expires="+ expDate. toGMTStr ing () ; // Объект и программы для приложения Favorites // — /* Объект "favorite". Свойства : f ullName - Полное описательное имя. cook - Код, используемый для cookie-набора urlpath - Полный URL (http://...) к сайту Методы: Enabled - Возвращает true, если cookie-набор ссьшки включен Checked - Возвращает слово "CHECKED" , если cookie-набор ссьшки включен HrlteAsCheckBox - Отправляет текст в документ в формате флажка WriteAsWebLink - Отправляет текст в документ в формате <а href . . . > function favorite (fullName, cook, urlpath) I th 1 s . f ul IName = f ul IName ; this . cook = cook; this. urlpath = urlpath; this. Enabled = Enabled; this. Checked = Checked; this. WriteAsCheckBox = WriteAsCheckBox; this.WriteAsWebLink = WriteAsWebLink; // Enabled - Enabled проверяет, существует ли cookie-набор // Результат - возвращает true, если cookie-набор существует, и false — если нет function Enabled () 'I var result = false; var FaveCookle = GetCookie ("Favorites"); If (FaveCookle != null) ¦i var searchFor = "<" + this, cook + ">"; var startOfCookle = FaveCookie. indexOf (searchFor) ; If (startOfCookle != -1) result = true; 1 ret urn result; // Checked - Checked проверяет, существует ли cookie-набор (с помощью Enabled) . // Результат - возвращает "CHECKED", если cookie-набор существует, и "" — если нет. // function Checked () Г if (this.Enabled() > return "CHECKED " ; return ""; > // // WriteAsCheckBox - Предпочтение может быть или обычным URL, или заголовком раздела. // Если путь URL — пустая строка, тогда предпочтение — заголовок // раздела. В списке определений появятся ссылки в соответствующем формате. // function WriteAsCheckBox (} il .// Проверить, это заголовок или обычная ссылка If (this.urlpath = "")
Избранные программные технологии Часть V // Это заголовок раздела result = '<dtxstrong>' + this . f ullName + '</strong>'; » else { // Это обычная ссылка result = '<ddxinput type="oheckbox" name="'+ this, cook + '" '+ this. Checked() + •onClick="SetFavoriteEnabled(this.name, this.checked);">'+ this .fullName; ) document.write(result); // Глобальная переменная: // NextHeading - Иногда требуется распечатать только заголовок, если предпочтение // установлено. Данная переменная помогает это сделать. См. WriteAsWebLink var NextHeading = " " ; // // WriteAsHebLink - Предпочтение может быть либо заголовком раздела, либо // обычным DRL. Ссылки появляются внутри списка определений // и соответствующим образом форматируются. functionWriteAsWebLink { ) ¦I var result = ' ' ; if (this.urlpath = "") I .NextHeading = this. fullName; // Это обычная ссылка 1 else if <this.Enabled<) || (GetCookie("ViewAll"> == "T")) ¦'{ if (NextHeading != "") I result = '<pXdtXstrong>' + NextHeading+ '</strong>' ; NextHeading = " " ; j result = result + '<ddXahref=" ¦ + this.urlpath + '">'+ this. fullName + '</a>' ; document.write (result); } // Глобальные переменные /* . . . . FaveList хранит список всех объектов предпочтений, которые объявляются ниже. Предпочтения с пустым urlpath находятся в заголовках раздела. var FaveList = new Array () ; ,// Раздел комиксов FaveList [1] = new favorite ("Comics", "", "") ; FaveList[2] = new favorite ("Dilbert" , "cdilb", "http://www.unitedmedia.com/comics/dilbert/ FaveList [3] = new favorite ("Doonesbury" , "cdoon", "http: //www.uexpress . com/cgi-bin/ups/mainindex. cgi?code=db" ) ; FaveList [4] = new favorite ("Mr. Boffo", "cboff", "http://www.uexpress . com/cgi-bin/ups/new_mainindex.cgi?code=mb") ,¦ // Раздел общих новостей FaveList [5] = new favorite ("General News", "", "") ; FaveList[6] = new favorite ("CNN", "ncnn", "http://www.cnn.com/"); FaveList [7] = new favorite ("NPR" , "nnpr" , "http://www.npr.org/news/") ; FaveList [8] = new favorite ("Boston Globe", "nbos" , "http://www.boston.com/") ; // Раздел компьютерной ш^дустрют FaveList [9] = new favorite ("Computer Industry", "", "") ; FaveList[10] = new favorite ("PC Week" , "ipcw" , "http://www.pcweek.com/");
Персонализацияи динамические страницы Глава 30 FaveList[ll] = new favorite ("TechWeb", "icmp", "http://www.techWeb.com/wire/wire.html"); FaveList[12J = new favorite("Netscape", "ntsc","http://devedge.netscape.com/"); FaveList[13] = new favorite("Microsoft", "micr","http://msdn.microsoft.com/"); // Раздел поисковых механизмов FaveList[14] = new favorite ("Search Engines", "", "") ; FaveList[15] = new favorite("Yahoo!", "syah","http://www.yahoo.com/"); FaveList[16] = new favorite("Alta Vista", "sav","http://www.altavista.com/"); FaveList [17] = new favorite ("Excite" , "sexc" , "http://www.excite.com/") ,- // Раздел аукционов FaveList[18] = new favorite("Auctions", "", "") ; FaveList[19] = new favorite("ebay", "ebay","http://www.ebay.com/"); FaveList[20] = new favorite("Yahoo Auctions", "yhac", "http://auctions.yahoo.com/"); // Раздел о разном ¦ FaveList[21] = new favorite ("Misc.", ""', "") ; FaveList[22] = new favorite("Today in History", "mtih", "http://www.thehistorynet.com/today/ today.htm"); FaveList[23] = new favorite ("Merriam-Webster' s Word of the Day" , "mwod" , "http://www.m-w.com/cgi- bin/mwwod.pl"); FaveList[24] = new favorite ("Quotes of the Day" , "mquot", "http://www.starlingtech.com/quotes/ qotd.html") ; // Подпрограммы записи страниц. // SendOptionsPage - Запись страницы выбора предпочтений function SendOptionsPage () document.write ( ' <hl>SelectFavorites</hl>' > ; document .write ( '<?orramethod=post>' ) ; .// Кнопка для просмотра страниц Favorites document.write ( '<input type=button value="Show Favorites" '+ 'onClick="'+ 'ReloadPage()'+';">'); // Ссылки будут выглядеть значительно лучие внутри описания listdocument.write ('<dl>')»" for (var i = 1; i < FaveList. length; i++) FaveList[i] .WriteAsCheckBox() ; // Записать каждый флажок document.write ( '</dlXp>5 ; ClearCookie("ViewAll"); document.write ( '</form>') ; ,// LoadOptions - Установка cookie-набора ShowOption, что заставляет страницу выбора // огтций появляться во время перегрузки страницы .// function LoadOptions () С Set.CookieEZ ("ShowOptions", "T") ; window.open(document.location.href, "_top", "") ; // ToggleView - Включение и выключение режима ViewAll. При включенном режиме все // ссылки выводятся на экран. При выключенном режиме будут выводиться // только выбранные предпочтения пользователя. function ToggleView() ¦i if (GetCookie("ViewAll") == "T") { ClearCookie("ViewAll"); else { var fiveYears = 5 * 365 * 24 * 60 * 60 * 1000; var expDate = new Date () ; expDate.setTime (expDate.getTime() + fiveYears);
Избранныепрограммные технологии SetCookie("ViewAll", "I", expDate, null, null, false); J window.open(document, location.href , "_top", " " ) ; 1 // SendPersonalPage - Запись страницы с категориями и ссылкам»!, предпочитаемыми // пользователей. Отображает только заголовки, если предпочтения разрешены function SendPersonalPage () i if (GetCookie("ViewAll"> != "T") document. write < ' <hl>YourFavorites : </hl> ' ) ; else document.wxite< '<hl>Links:</hl>") ; // Кнопки для просмотра опций или страниц "View All" document.write ( '<fornmethod=post> ' ) ; if (GetCookie("ViewAll") == "T") I document, write ( "<input type=button value="View Favorites" ' + "onClick="ToggleView();">' ) else ¦i document, write ( "<input type=button value="View All" ' + 'onClick= " ToggleView <) ;">') ; ) document, write ( '<input type=button ' + "value="Select Personal Favorites" ' + ' onClick="LoadOptions() ; ">' ) ; document. wri te ( 1</form>'> ; // Ссылки будут выглядеть лучше внутри списка определений- document .write ( ' <dl> ' ) ; for (var i = 1; i < FaveList. length; i++) FaveList[i] . WriteAsWebLink ( ) ; // Запись каждой ссылки document .write ( ' </dlXp> ' ) ; // Вспомогательные функции // isEnabled - Возвращает true, если разрешено предпочтение, указанное параметром name // __ ,_ function isEnabled(name) 1 var result = false; var FaveCookie = GetCookie("Favorites"); if (FaveCookie != null) f var searchFor = "<" + name + ">" ; var startOfCookie = FaveCookie .indexOf (searchFor) ; .if (startOf Cookie != -1) result = true; It return result; // AddFavorite- Разрешает предпочтение, заданное параметром name // function AddFavorite(name) f if (!isEnabled(name)) { var fiveYears = 5 * 365 * 24 * 60 * 60 * 1000; var expDate = new Date(); expDate. setTime (expDate.getTime (> + fiveYears ) ; SetCookie("Favorites", GetCookie("Favorites")+ "<" + name + ">", expDate, null, null,
Персонализация и динамические страницы Глава 30 // ClearFavorite - Запрещает предпочтение, заданное параметром name function ClearFavorite (name) if (isEnabled(name)) var FaveCookie = GetCookie ("Favorites") ; ¦var searchFor = "<" + name + ">"; var startOfCookie = FaveCookie. indexOf (searchFor) ; var NewFaves = FaveCookie. substr ing @, startOf Cookie)+ FaveCookie .substring(startOfCookie+searohFor. length,FaveCookie. length); var fiveYears = 5 * 365 * 24 * 60 * 60 * 1000; var expDate = new Date ( ) ; expDate.setTime (expDate.getTime () + fiveYears ) ; SetCookie ("Favorites", NewFaves, expDate, null, null, false); I } II // SetFavoriteEnabled - Включает (SetOn=true) или отключает (SetOn=False) // предпочтение, определенное параметром name // function SetFavoriteEnabled(name, SetOn) ¦( if (SetOn) AddFavorite (name); else ClearFavorite(name) ; // ReloadPage - Перегрузить страницу // " - —— function ReloadPage() I window.open(document.location. href, "_top", " ") ; 5 // Конец сценария —> </script> </head> <body> <script language=" JavaScript"> <!— Сокрытие сценария от не-JavaScript-браузеров Именно здесь выбирается страница для отправки- Обычно отсылаются персонализированные страницы предпочтений (при помощи SendPersonalPage) , Однако, если cookie-наборы ShowOptions установлены, то вместо них отправляется страница выбора оппий (через вызов SendOptionsPage) . ___. - - ___, if {GetCookie("ShowOptions") == "T") i Cl«arCookie("ShowOptions"); SendOptionsPage(); else ( SendPersonalPage( ) ; ) // Конец сценария --> </script> <center> This .is a very dull page unless you have a JavaScript enabled browser. <br> ¦</cenl:er> </body> </html>
Избранные программные технологии Часть V Если бы данная операция выполнялась без JavaScript, она проходила бы на сервере. Каждое обращение пре- предусматривало бы запуск сервером определенного вида сценария или программы, с целью прочтения пользо- пользовательских cookie-наборов и генерации страницы на лету. Благодаря JavaScript весь процесс проходит на кли- клиентском браузере, а сервер только загружает статичес- статическую страницу. Можно обойтись и без этого, поскольку страница может поступать из локального кэша клиен- клиента. Когда страница загружена, отправляются все ссыл- ссылки независимо от того, выбраны они или нет. С помо- помощью cookie-наборов и JavaScript клиент может решить, какие из них должны отображаться пользователю. В программе используются три различных cookie- набора. В наборе Favorites содержится уникальный код для каждой предпочитаемой ссылки. Cookie-набор View All переключается между выводом пользовательских предпочтений и всех возможных ссылок. Программа также может вывести на экран одну из двух страниц: одну — для выбранной ссылки и другую — для изме- изменения конфигурации и опций. Когда установлен cookie- набор ShowOption, на экране отображается страница выбора опций Options. В противном случае выводится обычная страница. На рис. 30.2 показана страница конфигурирования. 1'3 C:\My Documentstf)oe«triefits\JE Unleashed\NewLdition\Chapier 3D\Listtn.,. Щ\ Select Favorites ShowFawiritei Comics PDilbert П Doonesbury HMr.Boffo General News Г CNN RNPR H Boston Globe Computer Industry П PC Week DTecHWeb П Netscape Г Microsoft Search Engines d Yahool С AJta Vista Excite Auctions Febay РИСУНОК 30.2. Страница конфигурирования Favorites. Программа создает объекты, называемые, как не- несложно догадаться, "предпочтения". Каждое предпочте- предпочтение, по сути дела, — ссылка на другую страницу. Объект предпочтения содержит информацию о ссылке (URL), описание страницы и код, определяющий ее в строке cookie-набора Favorites. Кроме того, объект знает, как вывести себя на Web-странице в виде обычной ссылки для страницы Favorites, либо же в формате флажка для страницы Options. Серверы и браузеры, поддерживающие механизм cookie- шборов Если другие способы программирования для Web, такие как CGI или специальные серверные интерфейсы, требуют, чтобы сервер и браузер воспринимали cookie-наборы, то в JavaScript это требование относит- относится только к браузерам. Это означает, что JavaScript мож- можно безнаказанно пользоваться до тех пор, пока клиен- клиенты распознают JavaScript. Однако, многие Web-приложения могут смешивать JavaScript с другими средствами разработки, которые требуют от сервера восприятия cookie-на! РЕСУРСЫ Подробная информация, посвященная cookie-наборам находится на следующих Web-сайтах: Страница спецификации cookie-наборов компании Netscape: http://www.netscape.ee cookie_spec.html Браузеры, поддерживающие cookies-наборы: http:// www.research.digital.com/nsl/formtest/stats-by-test/ NefscapeCookie.html. Центр cookie-наборов: http://www.cookiecentral.com/ Web-браузеры, поддерживающие cookie-набора от Digital: http://www.research.digital.com/nsl/formtest/ sfats-by-test/NetscapeCookie.html. Robert's Brooks' Cookie Taste Test: http:// www.geocities.com/SoHo/4S35/cookie.html. Другие способы поддержки информации о состоянии Как упоминалось ранее, применению cookie-наборов присущи свои недостатки. Возможно, будет предпринята попытка избежать разногласий и найти другой способ поддержки состояния при переходе с одной страницы на другую. Существует два пути. Какой будет выбран, за- зависит от того, каким образом пользователи попадают с одной страницы на другую в рамках создаваемого сай- сайта. Главным ограничением этих методов является то, что они срабатывают при переходе с одной страницы на непосредственно следующую за ней. Если информа- информация о состоянии должна поддерживаться на протяже- протяжении целой последо! -и страниц, механизм дол- должен применяться на каждой странице. Строка запроса Если вся н; I, в основном, приходится на встро- встроенные в страницы гипертекстовые ссылки, в конце URL
Персонализация и динамические страницы потребуется добавить дополнительную информацию. Это обычно проделывается за счет добавления знака вопро- вопроса (?) в конце URL Web-страницы, за которым следует информация в кодированной форме, возвращаемая ме- методом escape(). Для отделения одной части информации от другой, используется амперсанд (&). Например, если разработчик пожелает отправить вместе с ссылкой параметры color=blue и size=extra large, ссылку должна выглядеть так: <а href= "/mypage.html?color=blueSsize=extra+large"> XL Blue</a> Этот формат подобен тому, что используется при передаче работы формы с помощью метода get. Следу- Следующая страница может считывать эту информацию, ис- Глава 30 пользуя свойства search объекта Location. Это свойство' называется search, поскольку многие поисковые серве- сервера используют эту часть URL для сохранения их поис- поисковых критерий. Далее рассматривается пример использования свой- свойства location.search, В данном примере имя текущей страницы отправляется как параметр в ссылке на дру- другую страницу. Другая страница считывает это свойство с помощью search и определяет, откуда перешел брау- браузер. В листинге 30.7 показана первая страница, содержа- содержащая ссылку. В листинге 30.8 представлена вторая страница, де- демонстрирующая использование location.search. В ней определяется, откуда пришел браузер. Листинг 30.7 Wherei .html <html> <head> <title>Where Was I? - Page K/title> </head> <body> <M>Where Was I? - Demonstration</hl> This page sets information which will allow the page it is linked to out where it came from. It uses values embedded in the link URL in order to do this He'll assume that any URL parameters are separated by an ampersand. Notice that there doesn't need to be any JavaScript code in this page. And now, <a href="where2.html?camefrom=Wherel.html?more=needless+stuff Let's go to Page 2.</a> </body> </html> Листинг 30.8 Where2.html <html> <title>Where Was I? - Page 2</title> <head> <7head> <body> <hl>Where Was I? - Demontration</hl> This page reads information which allows it to out where it came from. <p> <script languages"javascript"> <•— Начало сценария // WhereWasI // Считывание строки поиска для вывода того, что предоставила ссылка function WhereWasI (> { // Сохранить строку поиска в удобном месте (таким образом, чтобы лишний pas не // производить набор) var handyString = window, location, search; // Найти начало специальной переменной URL var startOfSource = handyString. indexOf ("camefrom="> ; // если присутствуем, найти конец переменной if (StartOfSource != -1) { var endOfSource = handyString.indexOf ("&", startOfSource+9) ; var result = handyString. substring(startOfSource+9, endOfSource) ; J
Избранные программные Часть V else var result = "Source Unknown"; // Невозможно отыскать строку "camefrom" return result; _} if (WhereWasI () != "Source Unknown") document,write ("You just came from <b>" + WhereWasI () + "</b>.<br>") else document.write ("Unfortunately, we don't know where you came from.<br>"); // Конец сценария —> </script> </body> </html> Скрытые переменные формы Метод, описываемый в предыдущем разделе, работает, пока пользователь перемещается по страницам с исполь- использованием ссылок. Для того чтобы выполнить это же за- задание, но только с формами, потребуется вместо пара- параметра location.search прибегнуть к скрытым переменным формы. Скрытые переменные формы обладают следующим форматом: <input type="hidden" name="H±ddenF±eldName" value= "HiddenFieldValuf> Для HiddenFieldNamen HiddeFieldValue можно ука- указать все, что угодно. Параметр value определять не обя- обязательно. Для использования скрытых полей код JavaScript необязателен. Они определяются в обычном HTML-до- HTML-документе, а не в дескрипторе <input>. Серверные сцена- сценарии, такие, как CGl-программы или программы, исполь- использующие API сервера, для чтения значений скрытых полей не обязательны. Форма, содержащая скрытые переменные, передает- передается в серверные сценарии или даже в функции JavaScript, которые выдают все, что знают о браузере, в отдельную Web-страницу, включая информацию о полях формы. Информация о скрытых полях находится в нижней час- части страницы. Она выглядит следующим образом; Form Post Data: Raw Form Data String: camefrom=where3.htmSotherStuff=I+don%27t+care camefrom=where3.htm otherStuff=1 don't care Резюме В главе рассматривались способы создания динамичес- динамических и персонализированных Web-страниц за счет под- поддержки информации о состоянии. Оказалось, что самый эффективный способ заключается в использовании cookie-наборов. cookie-наборы позволяют сохранять информацию на клиентском компьютере и применять ее в приложе- приложении с целью записи значений и другой важной инфор- информации. Учитывая широкомасштабность cookie-наборов, их можно применять как для простейших пар name=value, так и для более сложных форм. Хотя cookie-наборы и представляют самый эффек- эффективный метод поддержки информации о состоянии, су- существуют и другие способы, например, параметры стро- строки запроса URL и скрытые поля формы.
Выполнение поиска по шаблону с использованием регулярных выражений В ЭТОЙ ГЛАВЕ Создание регулярных выражений Синтаксис регулярных выражений Использование регулярных выражений Тестер регулярных выражений Пример: программа проверки правильности ввода телефонных номеров Одно из наиболее важных свойств JavaScript — это возможность выполнения поиска по шаблону. Поиск по шаблону в JavaScript осуществляется с помощью регуляр- регулярных выражений (Regular Expression). Эта идея была взята из наиболее удобного и доступного современного язы- языка с подобными возможностями — Perl. Поиск по шаб- шаблону позволяет отыскивать сложные образцы в строках. Для поиска по шаблону простейших выражений без ре- регулярных выражений потребуется очень много строк кода. В главе рассматривается синтаксис, необходимый для создания регулярных выражений. Создание регулярных выражений Хотя, на первый взгляд, регулярные выражения могут показаться чем-то необычным, разработчик должен по- понимать, что это не просто строки, содержащие буквы, цифры и символы. Специалист создает шаблон, aJavaScript выполняет поиск. Для упрощения работы регулярные выражения были помещены в объект RegExp. Создание регулярных выражений очень напоминает создание строк при помощи объектного конструктора или опера- оператора присваивания (=). Конструктор RegExp() С тех пор как регулярные выражения приобрели объек- объектную оболочку в JavaScript, можно просто вводить шаблон как аргумент в конструктор RegExpQ, а затем присваи- присваивать результирующий объект переменной. Например, ниже создается объект RegExp с именем firstName, со- содержащий шаблон John. var firstName=new RegExp ("John") He переживайте, если пока еще не понятно, что оз- означает понятие шаблон (это обсуждается немного поз- позже); сфокусируйте внимание на синтаксисе, применяе- применяемом при создании объекта RegExp. Оператор присваивания Второй путь создания регулярных выражений — присва- присваивание шаблона непосредственно переменной и предо- предоставление JavaScript возможности проверять, чтобы пе- переменная была объектом RegExp. Следующая строка кода создает объект RegExp с именем firstName, содер- содержащий шаблон John. var ?irstName=/John/; Разработчик наверняка заинтересуется, а как же JavaScript может знать, что firstName должен быть объек- объектом RegExp, а не объектом String. Различие состоит в том, что строки заключаются в двойные или одинарные кавычки, в то время как шаблоны — в символы косых с правым клоном (/). Заметьте, что конструктор RegExp() обходится без такого символа поскольку он отличается от конструктора String(). Синтаксис регулярных выражений После того как стало понятно создание объектов регу- регулярных выражений, можно перейти к синтаксису, необ- необходимому для создания реального шаблона. Как упоми- упоминалось ранее, синтаксис шаблонов взят непосредственно из Perl. При наличии определенных знаний по этому языку, следующие задания покажутся весьма простыми. В табл. 31.1 перечислены все специальные символы по- поиска по шаблону.
Избранные программные технологии Часть V Таблица 31.1 Символы поиска по шаблону Символ Описание \w Любой символ в слове (алфавитно-цифровой). \W Неалфавитно-цифровой символ. \s Любой пробельный символ (символы табуляции, новой строки, возврата каретки, перевода страницы, вертикальной табуляции). \S Непробельный символ. \d Цифровой символ. \D Нецифрой символ. [\Ь] Символ забоя. Любой символ за исключением символа новой строки. ,[...] Любой символ, указанный в скобках. |[~...] Любой символ, за исключением перечисленного в скобках, [х-у] Символы в промежутке от х до у. ["х-у] Символы, не входящие в промежуток от х до у. {х,у} Предыдущий элемент должен быть найден не менее х раз, но не более у раз. {х,} Предыдущий элемент должен быть найден не менее х раз. {х} Предыдущий элемент должен быть найден точно х раз. ? Предыдущий элемент должен быть найден однажды или вообще не найден. + Предыдущий элемент должен быть найден хотя бы один раз. * Предыдущий элемент должен быть найден неограниченное количество раз или вообще не найден. II Должно быть совпадение либо в выражении справа, либо слева от символа |. (...) Группировка всех элементов в круглых скобках в подшаблон. \х Поиск тех же символов, что и полученных из подшаблона в группе х. Группы, заданные в круглых скобках, нумеруются слева направо. Поиск с начала строки или же с начала первой строки в многострочных данных. $ Поиск с конца строки или с конца последней строки в многострочных данных. \Ь Позиция между знаком, входящим в слова, и не входящим в слова. \В Позиция, не находящаяся между знаком, входящим в слова, и не входящим в слова. Некоторые их перечисленных выше символов — до- достаточно просты для понимания, в то время как неко- некоторые — не столь очевидны. В следующих разделах де- детально рассматриваются все символы. \w и \W Строчная w (\w) определяет любой символ, который находится в словаре. К таким знакам принадлежат ал- алфавитно-цифровые символы. Это означает, что им мо- может быть либо буква (a-z), либо цифра @-9). Прописная W отличается тем, что определяет символы, не входящие в слова. Например, шаблон поиска var pattern=/\w\W/; находит Ь? в строке поиска, но знак ?Ь не будет найден, поскольку первым должен быть символ буквы или циф- цифры, а вторым — символ, не являющийся буквой или цифрой. \sn\S Строчная s находит любой пробельный символ. Про- Пробельные символы — это символы табуляции, символы новой строки, возврата каретки, перевода страницы и вертикальной табуляции. Прописная S (\S) отличается тем, что находит непробельные символы. Например, шаблон поиска var pattern=/\s\S/; найдет символ возврата каретки, за которым следует g, но не сможет найти g, за которой следует символ воз- возврата каретки. \dn\D Строчная d (\d) отыскивает любую цифру @—9), а про- прописная D (\D) является противоположностью, выполняя поиск любого символа, не являющегося цифрой. Напри- Например, шаблон поиска
Выполнение поиска по шаблону с использованием регулярных выражений var pattern=/\d\D/; найдет 4р в строке поиска, но не сможет найти р4, по- поскольку цифра должна находиться на первом месте, а не на втором. [\Ь] Строчная b в скобках |\Ь] используется для поиска сим- символа забоя (backspace). Существует не так уж и много случаев, когда требуется поиск символа забоя, однако если уж подобная потребность возникла, постарайтесь использовать именно этот шаблон. Точка Точка (.) применяется для поиска всех знаков, за исклю- исключением знаков новой строки. '[...] И [а...] Скобки используются для поиска одного символа, нахо- находящегося внутри скобок. Если после левой скобки на- находится символ Л, выполняется поиск любого символа, не входящего в перечисленные в скобках. Например, шаблон поиска var pattern=/[abc] [Adef]/,- найдет ag в строке поиска, но не сможет найти ga, по- поскольку на первом месте должны стоять либо а, либо Ь, либо с, а на втором — d, e или f. [х-у] и [лх-у] Черта внутри скобок используется для определения ди- диапазона вместо перечисления всех символов. Обнаружи- Обнаруживается любой символ в рамках диапазона х-у, появляю- появляющийся в строке поиска. Если сразу после скобки следует символ л, находится любой символ, не входящий в диа- диапазон. Предыдущий пример можно переписать следую- следующим образом: var pattern=/[a-c] [Ad-f}/; Этот шаблон найдет в строке поиска ag, но не смо- сможет найти ga, поскольку на первом месте должны сто- стоять а, Ь, или с, а на втором — d, e или f. {х,у}, {х,} и {х} Существует несколько вариантов синтаксиса с фигурны- фигурными скобками; всех их связывает повторение символа, следующего за левой фигурной скобкой. В данном син- синтаксисе х и у представляют цифры. Если применяется и х, и у, тогда предыдущий символ должен быть найден, по меньшей мере, х раз, но не более у раз. Если за х следует запятая, тогда предыдущий символ должен быть найден х раз. И наконец, если в скобках находится толь- только х, но без запятой, тогда предыдущий символ должен Глава 31 быть найден в точности х раз. Например, шаблон поис- поиска var patterns/cho{1,2}se/; найдет chose и choose в строке поиска, но не сможет найти chooose, поскольку символ о должен присутство- присутствовать хотя бы один раз, но не более двух раз. ?, + И * Существует три операции, выполняющие определенные действия, связанные с фигурными скобками, а именно: знак вопроса (?), плюс (+) и звездочка (*). Знак вопро- вопроса (?) находит предыдущий символ один раз или вооб- вообще не находит такового. Плюс (+) отыскивает предыду- предыдущий знак хотя бы раз. И наконец, звездочка (*) находит предыдущий знак любое количество раз или вообще не находит. Например, шаблон поиска var pattern=/ab?c/; найдет abc или ас в строке, но не сможет найти abbe, поскольку символ "Ь" должен быть найден один раз или вообще не найден. Логическое или (|) Вертикальная черта (|) действует как логическое ИЛИ (OR) и отыскивает символ либо справа, либо слева от вертикальной черты. Например, шаблон поиска var pattern=/cat|dog/; найдет в строке cat или dog. (...) Круглые скобки позволяют выполнять поиск элементов, помещенных внутрь других элементов. Например, шаб- шаблон поиска var pattern=/f(a|o)r/; найдет в строке поиска far или for. \Х \х в комбинации с круглыми скобками используется для поиска символов подшаблона с номером группы х. Груп- Группы обозначаются круглыми скобками и нумерация их следует слева направо. Например, шаблон поиска var pattern=/f(a|o)r\l/; осуществит поиск в строке fara и foro, но не faro и fora. Когда символ л находится перед текстом, поиск будет производиться только в том случае, если текст появля- появляется в начале строки или в начале первой строки мно- многостроковой последовательности. Например, следующий шаблон поиска
Избранные программные технологии Часть V var pattern=/AThe/; выполнит поиск слова The, если оно присутствует в на- начале последовательности или в начале одиночной стро- строки, $ Символ $ является полной противоположностью симво- символу Л. Например, если знак $ помещается перед текстом, поиск будет происходить в том случае, если текст появ- появляется в конце поисковой строки или в конце последней строки в многостроковой последовательности. Следую- Следующий шаблон поиска var pattern=/Ahome/; приведет к поиску слова home, если оно появляется в конце последовательности или одиночной строки. Символ Описание \Ьи \В Строчная b (b\) находит положение между словарным и несловарным знаком. Имейте в виду, что словарный знак является алфавитно-цифровым. Это означает, что он может быть либо буквой (a—z), либо цифрой @~9). Про- Прописная В (\В) — напротив, находит позицию, выходя- выходящую за пределы словарного и несловарного знаков. Например, шаблон поиска var pattern=/cat\b/; найдет слово cat, за которым следует пробел. Пробел является несловарным символом. Возможно, возникнет вопрос, а что, если потребует- потребуется отыскать особый символ, например, символ $? Все особые символы представляются с использованием на- наклонной черты влево (\), за которой следует собствен- собственно символ. В табл. 31.2 перечислены все символы, кон- конфликтующие с символами поиска по шаблону. Таблица 31.2 Специальные символы Символ Описание \f \г \t \v V \\ \. V V- \? \| Перевод страницы. Новая строка. Возврат каретки. Табуляция. 'Вертикальная табуляция Наклонная черта вправо Наклонная черта влево. Точка. Звездочка. Плюс. Знак вопроса. Вертикальная черта. \( Открывающая круглая скобка. \) Закрывающая круглая скобка. \[ Открывающая квадратная скобка. \] Закрывающая квадратная скобка. \{ Открывающая фигурная скобка. \} Закрывающая фигурная скобка. \ХХХ Символ ASCII, представленный восьмеричным кодом XXX. \хНН Символ ASCII, представленный шестнадцатиричным кодом НН. \сХ Управляющий символ, представленный X. И наконец, последняя часть синтаксиса позволяет устанавливать атрибуты, связанные с регулярными вы- выражениями. Атрибуты сведены в табл. 31.3. Таблица 31.3 Атрибуты поиска по шаблону Символ Описание g Глобальный поиск. Найти все возможные совпадения. i Поиск без учета регистра. В отличие от ранее рассмотренного синтаксиса, эти атрибуты устанавливаются за пределами наклонных черт влево, определяющих шаблон при создании регулярных выражений. Регулярные выражения для глобального поиска слова "bear" выглядит следующим образом: var animalSearch=/bear/g; В случае создания регулярного выражения с исполь- использованием конструктора RegExp() атрибуты необходимо сохранить как строку и передать ее во втором аргументе конструктора. Регулярное выражение для поиска слова "bear" без учета регистра выглядит следующим образом: var animalSearch=new RegExp ("bear", "i"); Использование регулярных выражений Сейчас, когда необходимый шаблон уже присвоен объек- объекту RegExp, что же с ним делать дальше? Существует два пути применения регулярных выражений. Первый зак- заключается в использовании методов объекта RegExp, a второй — в использовании методов объекта String. В конечном итоге регулярные выражения смогут начать поиск по шаблону внутри строки. Методы поиска по шаблону, которые обеспечивает объект RegExp, пред- представлены в табл. 31.4. Обратите внимание, эти методы требуют передачи в качестве аргумента объекта String, в котором выполняется поиск.
Выполнение поиска по шаблону с использованием регулярных выражений Таблица 31.4 Методы поиска по шаблону в объекте RegExp. Метод Описание exec (s(r) Осуществляет поиск по шаблону sfr и возвращает результат. test (sfr) Осуществляет поиск по шаблону str и возвращает true, если соответствие найдено, и false — в противном случае. (sfr) Тоже самое, что и метод exec (sfr). Методы поиска по шаблону, поддерживаемые объек- объектом String, перечислены в табл. 31.5. Эти методы требу- требуют передачи в качестве аргумента объекта RegExp, в котором совершается поиск. Таблица 31.5 Методы поиска по шаблону в объекте String. Метод Описание match (regExpObj) Осуществляет поиск шаблона regExpObj внутри строки и возвращает результат. replace (reqExpObj, sfr) Заменяет все вхождения шаблона regExpObj на sfr. Возвращает позицию вхождения regExpObj внутри строки. Производит разбиение строки на max частей в местах, где встречается вхождение regExpObj. Подстроки возвращаются в виде массива. search (regExpObj, str) split (regExpObj, max} ПРИМЕЧАНИЕ Методы, перечисленные в табл. 31.4 и 31.5, не явля- являются единственными, связанными с объектами String и RegExp. Были представлены только наиболее распрос- распространенные методы, применяемые для поиска и замены. Тестер регулярных выражений Замысловатый синтаксис, используемый при создании шаблонов для регулярных выражений, может несколь- несколько запутать разработчика, в особенности, если необхо- необходимо смешивать и находить функции для создания слож- сложных поисковых шаблонов. Именно по этой причине в главе рассматривается программа для тестирования ре- регулярных выражений. Она поможет не только изучить сам процесс создания регулярных выражений с помощью конструктора RegExp(), но также и создавать и тестиро- тестировать собственные шаблоны поиска. Как показано на рис. 31.1, данная программа выпол- выполняет поиск и замену в поисковой строке, в строке заме- замены и шаблоне, который был введен. Преимущество этой Глава 31 программы заключается в возможности создания стро- строки поиска и шаблона, а после — тестирования того, что шаблон работает именно так, как было задумано. Исход- Исходный код программы показан в листинге 31.1. Regular Expression Tester Search String: ja big cat Replace String: ]T Attributes: jg Pattern: jbig Result: ]« РИСУНОК 31.1 Тестер регулярных выражений Листинг 31.1 Тестер регулярных выражений <html> <head> <title>Regular Expression Tester</title>- <script language="JavaScript"> <!— Начало сценария // Функция осуществляет поиск по шаблону в // searchstr function searchForPattern(searchstr, pattern, REattributes, theResult) r //Создание объекта регулярного выражения var regExpObj = new RegExp(pattern,REattributes); //Заполнение поля результата результатами поиска theResult.value = regExpObj.exec(searchstr); 1 // Эта функция заменяет на replaceStr все // вхождения шаблона в searchstr function replacePattern(searchstr,replaceStr, pattern,REattributes,theResult) i //Создание объекта регулярного выражения var regExpObj = new RegExp(pattern,REattributes); //Заполнение поля результата результатами //поиска. theResult.value = searchstr.replace(regExpObj,replaceStr); У/ Эта функция очищает все поля страницы function clearFields(fieldl, field2, field3, field4, field5)
Избранные программные технологии Часть V fieldl.value = field2.value = field3.value = field4 .value = field5.value = // Конец сценария —> </script> </head> <body> <center> <hl>Regular Expression Tester</hl> <form name="niyForm""> <table board=0> <tr align=right> <td>Search String:</td> <tdxinput type="teact" name="searchString"X/td> </tr> <tr align=right> <td>Replace S tring:</td> <tdxinput type="text" name="replaceString"x/ td> </tr> <tr align=right> <td>Attributes:</td> <tdxinput type="text" name="REattributes"X/td> </tr> <tr align=right> <td>Pattern: </td> <td><input type="text" name="pattern"X/td> </tr> </table> <br> <input type="button" value="Search for pattern" onClick="searchForPattern(searchstr ing. value, pattern.value, BEattributes.value, result)"> <input type="button" value="Replace pattern" onClick="replacePattern(searchstring.value, replaces tring. value, pattern.value, FEattributes.value, result) "> <input type="button" value="Clear" onClick="clearFields(searohstring, replacestring, pattern, REattributes, result)"> <brXhrXbr> Result: <input type="text" name="result"> </center> </body> </html> Тестер регулярных выражений можно условно раз- разбить на четыре основные части: пользовательский интер- интерфейс, функция поиска, функция замены и функция очи- очистки полей. Пользовательский интерфейс Пользовательский интерфейс тестера регулярных выра- выражений состоит из формы с пятью текстовыми окнами и трех кнопок. Текстовое окно searchString обеспечива- обеспечивает место для ввода строки, поиск которой осуществля- осуществляется по определенному шаблону. Текстовое поле ввода replaces tring обеспечивает пространство для ввода стро- строки, используемой для замены частей searchString, где отыскивается соответствие. Значение из этого поля при- применяется после щелчка на кнопке Replace Pattern. Та- Такие атрибуты поиска по шаблону, как глобальный по- поиск/замена и поиск без учета регистра, помешаются в текстовом поле ввода attributes. Текстовое поле ввода pattern обеспечивает место для ввода шаблона регуляр- регулярного выражения, по которому выполняется поиск в searchString. После щелчка на кнопках Search for Pattern или Replace Pattern результат поиска/замены помещает- помещается в окно result. Функция поиска После щелчка на кнопке Search for Pattern обработчик событий onClick вызывает функцию searchForPattern. Эта функция передает конструктору шаблон, л также информацию об атрибутах, введенную в HTML-форму, с целью создания объекта RegExp с именем regExpObj. Метод regExpexec() используется для поиска по шабло- шаблону в поисковой строке, которая была введена в форму. Результат поиска помещается в текстовое поле result. Если же соответствие не найдено, упомянутое поле ос- остается пустым. Функция замены После щелчка на кнопке Replace Pattern обработчик со- событий onClick вызывает функцию replacePattern(). Эта функция передает конструктору шаблон, а также инфор- информацию об атрибутах, введенную в HTML-форму, с це- целью создания объекта RegExp с именем regExpObj. Ме- Метод replace() объекта searchStr применяется для замены на repIaceStr вхождений шаблона в searchStr. Затем ре- результат поиска и замены помещается в текстовое поле result. Если соответствие не найдено, в текстовое поле result помещается searchStr. Функция очистки После щелчка на кнопке Clear обработчик событий onClick вызывает функцию clearFields{). Эта функция произво- производит очистку всех текстовых полей.
Выполнение поиска по шаблону с использованием регулярных выражений Пример: программа проверки правильности ввода телефонных номеров Итак, читатели уже знакомы с регулярными выражения- выражениями, знают, как их создавать, а также имеют программу, которая поможет в определении шаблонов поиска. Но как применить регулярные выражения для решения ре- реальных задач? В современном Internet превалирует элек- электронная коммерция. Поэтому огромную роль играет проверка ввода телефонных номеров, адресов и номеров кредитных карточек. Многие виды проверок, например, кредитных карточек, должны выполняться на серверной части, однако проверка статической информации может проводиться и на стороне клиента. Один из видов ин- информации, проверяемой на серверной части, связан с территориальными кодами. Поскольку они меняются не очень часто, их можно поместить на Web-страницу и выполнять проверку с использованием регулярных вы- выражений в JavaScript. В Этом разделе рассказывается применение регуляр- регулярных выражений для проверки территориальных кодов перед тем, как разрешить пользователю продолжать ра- работу. Предположим, что создается Web-сайт для компа- компании North Caroline, торгующей различным хламом. Прежде чем пользователь сможет продолжить составлять заказ, следует убедиться, что компания имеет коррект- корректный телефонный номер, относящийся к Северной Ка- Каролине. В противном случае могут возникнуть пробле- проблемы с отгрузкой товара. Было бы разумно поместить все номера Северной Каролины на Web-страницу и с их помощью проверять корректность введенного номера. Однако можно прове- проверить правильность ввода территориального кода, который должен относиться к Северной Каролине. Если клиент допустил ошибку при вводе кода, его можно предупре- предупредить и предложить ввести номер Северной Каролины. Если же код правильный, формирование заказа можно продолжить. За счет использования поисковых шаблонов для те- телефонных номеров Северной Каролины, можно быстро определить корректность номера введенного пользова- пользователем. Все телефонные номера состоят из трехцифрового территориального кода, за которым следует трехцифро- вая приставка, а за ней — четырехцифровое расширение. Шаблон будет выглядеть следующим образом: ###-###- ####. Поскольку знак # обозначает цифру, можно при- прибегнуть к синтаксису регулярных выражений \d для циф- цифры в этих позициях. Поисковый шаблон станет таковым: /\d\d\d-\d\d\d-\d\d\d\d/ 'Обратите внимание, что наклонная черта вправо ука- указывает на конец и начало шаблона. Поскольку извест- Глава 31 но, что в Северной Каролине имеется только шесть ко- кодов (828, 252, 704, 919, 910, 336), то их можно задейство- задействовать в шаблоне: /<828|252j704|919|9101336)-\d\d\d-\d\d\d\d/ Добавьте подшаблоны в основной шаблон, поместив все возможные территориальные коды в круглые скоб- скобки и отделив каждый код вертикальной чертой. Верти- Вертикальная черта означает, что должна предприниматься попытка поиска значения справа или слева, т.е. логичес- логическая операция ИЛИ. Если пользователь вводит террито- территориальный код, определенный в списке, результат поис- поиска будет положительным. Теперь, когда составлены все поисковые шаблоны для телефонных номеров Северной Каролины, потребу- потребуется построить пользовательский интерфейс и протести- протестировать шаблоны. Если отыскивается шаблон в строке, содержащей правильный телефонный номер, то возвра- возвращается соответствующий телефонный номер. С другой стороны, если ищется шаблон в строке с неправильным телефонным номером, будет возвращен NULL. По на- наличию NULL можно судить, является ли введенный пользователем номер правильным. Следующая функция JavaScript реализует описанную выше операцию. function validatePhone (areaCode,prefix, extension) i .//Сборка телефонного номера var phoneNum = new String (areaCode + "-" + prefix + "-" + extension) ; //Создание шаблона регулярного выражения, //выполняющего поиск телефонного номера с //территориальными кодами 828, 252, 704, 919, //336. var regExpObj = / (82812521 704 | 919 | 910 | 336) - \d\d\d-\d\d\d\d/; if (regExpObj .exec (phoneNum) = null) f alert (phoneNum + " does not contain a valid ^North Carolina area code ! " ) ; else f alert {"Thank you for your order!"); Если добавить в функцию некоторый HTML-код, Получится полнофункциональная программа проверки телефонных номеров. В листинге 31.2 представлен пол- полный исходный код такой программы. Листинг 31.2. Проверка введенного телефонного номера. <html> <head> <title>Phone Number Validation</title> <script language="JavaScript"> <! — Начало сценария
Избранные программные технологии Часть V function validatePhone(areaCode,prefix,extension) //Сборка телефонного номера var phoneNum = new String (areaCode + " " + prefix + " " + extension) ; //Создание шаблона регулярного выражения, //выполняюцего поиск телефонного номера с //территориальными кодами 828, 252, 704, 919, //910, 336 var regExpObj = / (828 \d\d\d-\d\d\d\d/; if (regExpObj . exec (phoneNum) = null) alert (phoneNum + does not contain a valid ~"North Carolina area code'"); I else ¦I alert ("Thank you for your order I // Конец сценария—> </script> </head> <body> <center> <hl>NC Sales Company</hl> Thanks for your order. Please provide us with your North Carolina phone number so we can contact you if tne в are any problems shipping your order. <?orm name="forml"> Phone Number: <input type="text" size=3 maxlength=3 name="area">- <input type="text" size=3 maxlength=3 name="prefix">- <input type="text" size=4 maxlength=4 name="extension"> <brXbr> <input type="button" value="Submi t" onClick="validatePhone(area.value, prefix.value, extension.value)"> </form> </center> </body> </html> Теперь можно приступить к тестированию програм- программы. При наборе правильного телефонного номера, на- например, 919-293-4444, и щелчке на кнопке Submit ото- отображается окно предупреждения, сообщающее об обработке заказа. При вводе неправильного номера, ска- скажем, 918-293-4444, и щелчке на кнопке Submit поиск завершается неудачей и появляется сообщение об ошиб- ошибке (см. рис. 31.2). NC Sales Company Thanks foryour ore Please provide us withyourNorth Carolina phone number so we can contact you ifthere are any problems hipping your order. Phone Number: '|91в1|гэз1 [Л РИСУНОК 31.2 Программа проверки правильности вб телефонного номера. Резюме Глава была посвящена использованию объекта регуляр- регулярного выражения. Подробно рассматривались способы создания шаблонов поиска и объектов RegExp, в кото- которых эти шаблоны хранятся. Кроме того, исследовались особенности применения шаблонов, предназначенные для поиска текста. При этом использовались методы |бъсктов RegExp и String. Для иллюстрации работы с регулярными выражени- выражениями рассматривался тестер таких выражений. Эта ути- утилита незаменима при создании и тестировании сложных поисковых шаблонов. Программа проверки правильно- правильности ввода телефонных номеров продемонстрировала один из способов реального применения регулярных выражений.
Технология обработки данных со стороны клиента В ЭТОЙ ГЛАВЕ Определение источника данных: клиент или сервер? Что такое клиентская таблица? Создание таблиц поиска Создание поискового пользовательского интерфейса Обработка поисковых запросов Отображение результатов поиска Запуск приложения Web предлагает поистине революционный подход к созданию приложений баз данных, обеспечивая возмож- возможности доступа к удаленным базам данных через Web- браузер и возврате результатов в HTML-формате. Не- Несмотря на то что этот способ практикуется, в основном, при работе с CGI-сценариями, для получения доступа к данным можно воспользоваться и JavaScript. Обычно, когда говорят о доступе к базам данных в Web, имеют в виду, что данные находятся на сервере. Однако JavaScript обеспечивает работу с данными и на стороне клиента. В этой главе рассматривается, как при помощи JavaScript можно манипулировать данными на клиентской части, что может оказаться альтернативой CG1 или другим серверным решениям. Определение источника данных: клиент или сервер? Прежде чем углубиться в сам процесс работы с клиен- клиентскими данными в JavaScript, стоит разобраться, имеет ли все это смысл. Несмотря на то что клиентские дан- данные могут иметь различные типы, они будут рассмат- рассматриваться как таблицы баз данных. Например, разработ- разработчик желает получить данные из реляционной базы данных и преобразовать их в структурированный набор данных JavaScript, хранящийся в HTML-файле или на клиентском компьютере. Поскольку в главе использует- используется подход, ориентированный на базы данных, на набор данных JavaScript ссылаются как на таблицу клиентс- клиентской части. Таблицы клиентской части имеют два главных ог- ограничения. Первое: базы данных рассчитаны только на чтение. Поскольку данные внедрены в HTML-код, пользователи не смогут добавлять, изменять или сохра- сохранять эти данные на клиентской части. Если появляется необходимость в корректировке тех же данных на сер- серверной части, теоретически это возможно. В таком слу- случае, если происходят какие-либо изменения, клиентс- клиентскую базу данных потребуется перезагрузить. Так или иначе, пока разработчик не преодолеет множество пре- преград, таблица клиентской части будет предназначаться только для чтения. Второе ограничение связано с тем, что базы данных должны иметь относительно небольшие размеры. Дан- Данные хранятся в HTML-файле. Когда пользователь по- получает доступ к Web-странице, производится ее полная загрузка. Вряд ли кто-то пожелает внедрить в файл базу данных объемом в 100000 записей. Даже если пользо- пользователь обладает прямым подключением к Internet, все равно длительность загрузки приведет к некоторым не- неудобствам. Максимальный размер набора данных зависит от контекста. При создании таблицы клиентской части, которая будет передаваться со скоростью 28.8 Кбит/с для модема 56 Кбит/с, размер таблицы можно ограни- ограничить до 1000 записей. Однако, при создании intranet- решения, которое предусматривает быстрое соединение, границы можно расширить. Итак, с ограничениями должно быть все ясно, так почему же таблицы клиентской части все еще исполь- используются, если существует множество других способов работы с различными видами баз данных? На то име- имеется два объяснения. Во-первых, по ряду причин, с по- помощью таблицы клиентской части можно получить бо-
Избранные программные технологии Часть V лее простые решения, чего нельзя сказать о нариях и других средствах Web-сервера, принимая во внимание статичность и относительно малые размеры набора данных. Во-вторых, поскольку все данные, по- поисковый механизм и пользовательский интерфейс нахо- находятся на клиентской части, то доступ к серверной час- части совершенно не нужен. В результате существенно увеличивается скорость поиска и минимизируется до- дополнительная нагрузка на сервер, необходимая для осу- осуществления поиска. Многие станут возражать, что несмотря на переме- перемещение данных на сторону клиента, данные все равно проходят через серверную часть при загрузке страницы. И это правда. Однако, сервер не должен выполнять CGI- поиск, а только отправить клиенту HTML-файл. Поскольку корпорации разворачивают интрасети, в Web переносится большое количество маленьких сете- сетевых приложений. По причине того, что многие из них ориентированы на базы данных, будет расти трафик корпоративных Web-серверов. В некоторых случаях таб- таблицы клиентской минимизируют загрузку сервера. Од- Одним из примеров является приложение списка телефон- телефонных номеров компании. Можете назвать компанию, которая бы не имела такого списка, по крайней мере, на бумаге? В данной главе рассматривается именно этот пример, поскольку он более всего соответствует приме- применению клиентских данных для решения задач современ- современного бизнеса. Что такое клиентская таблица? Для Web-разработчиков термин таблица ассоциирует- ассоциируется с HTML-таблицами, которые создаются при помо- помощи дескрипторов <table>. Однако эта тема в данной главе не затрагивается. Поскольку речь идет о приложе- приложениях баз данных термин таблица ассоциируется с таб- таблицей, содержащей строки и столбцы в формате реля- реляционных баз данных. На рис. 32.1 показана типичная таблица баз данных. Существует множество различных способов работы с данными, а также выполнения их поиска, что в большей части зависит от способности программных средств управлять базами данных. В этом разделе под термином таблица подразумевается табли- таблица базы данных. К сожалению, работа с реляционными таблицам на клиентской части JavaScript посредством доступа к ба- базам данных будет невозможна несмотря на то, что эту операцию можно проводить на серверной части. Необ- Необходимо переводить базы данных в структурированный формат, в котором может работать код JavaScript. В JavaScript основной используемой организационной структурой является массив. Можно получить доступ к любому элементу массива JavaScript и выполнить вы- вычисления, как это проделывает реляционная Ьаза дан- данных с каждой записью во время поступления запроса. На рис. 32.2 проведена параллель между данными в ре- реляционной таблице и данными в массиве. ¦РИСУНОК 32.1. Таблицареляционной базы данных. Ordered Set of Tabula- Data Relational Table Best Hovies Casablanca Chariots of Fire African Queen A Room With a ¦¦ ¦. !wn. and the Beast Dances With Wolves Forrest Gump JavaScript Array bestMovies = newArrayG) >estMovies[1l = "Casablanca" bestMo\ries[2] = "Chariots of Fire* bestMovies[3] = "African Queen" bestMovies[4] = "A Room With a view" bestMoviesp] = "Beauty and the Beast" bestMovies[6] = "Dances With Wolves" bestMoviesp] = "Forrest Gump" РИСУНОК 32.2. Работа с набором табличных данных в зависимостиотконтекста. Создание таблиц поиска Первый шаг, который потребуется предпринять при работе с таблицами клиентской части JavaScript — со- создать саму таблицу. Таблица клиентской части не мо- может быть внешним файлом, поэтому все данные долж- должны быть внедрены в HTML-файл. Но для того, чтобы информация принесла реальную пользу, необходимо структурировать ее таким образом, чтобы поиск и вос- восстановление данных проводились при первой же необ- необходимости. Как упоминалось ранее, одной из опций для струк- структурирования клиентских данных является одномерный массив. Например, если поместить в массив полный список имен служащих, это будет выглядеть следующим образом: var employees = new Array A0) employees[1] = "Richard" employees[2] = "David" employees[3] = "Rachel" employees[4] = "Mark"
Технология обработки данных со стороны клиента employees[5] = "Mellon" employees[6] = "Margo" employees[7] = "Darius" employees[8] = "Dan" employees[9] = "Dave" employees[10] = "Pepe" Далее этот массив можно использовать и внутри его осуществлять поиск отдельных элементов, базируясь на информации, которая была вынесена из главы ]1. В данном случае одномерный массив не играет большой роли, поскольку во многих таблицах поиска находится большое количество столбцов для прослеживания дан- данных. В списке телефонов необходимо предусмотреть имя служащего, название организации, отдел, расшире- расширение телефонного номера, адрес электронной почты. Более эффективный способ заключается в создании пользовательского объекта employee, а после — группи- группировки данных о служащих в одномерный массив. Это позволит не только сохранить многочисленные столб- столбцы в объекте, но и работать с объектами employee как собирательной группой. Для определения объекта employee потребуется со- создать метод конструктора, как показано ниже: function employee(FirstName, LastName, Title, Department, PhoneExt, EmailAddress) { this.FirstName = FirstName; this. LastName = LastName; this.Title = Title; this. Department = Department; this. PhoneExt = Phone Ext; this. EmailAddress = EmailAddress; ) После создания конструктора можно приступить к созданию объектов employee и помещению их в контей- контейнерный массив empList. Для каждого служащего будет достаточно одной строки кода. Ниже показаны приме- примеры для пяти служащих из всех 105: empList[l] = new employee("Richard", "Wagner", "Chief Technology Officer", "RSD", 00", "rwagner@acadians.com"); empList[2] = new employee("Grady", "Anderson", "Programmer", "R&D", 98", "grady@acadians.com"); empList[3] = new employee ("Thomas", "Sprat", "Marketing Manager", "Marketing", 56", "tsprat@acadians.com ") ; empList[4] = new employee("William", "Cleyball", "Marketing Manager", "Marketing", 51", "wcal@acadians.com ") ; ¦empList[5] = new employee ("Fred" , "Tortallini" , "Marketing Manager", "Marketing", 04", "t.ort@acadians.com "); Сейчас все данные о служащих охвачены в структур- структурном формате, что очень необходимо для JavaScript. Глава 32 примечание ^ _ ^ ^1Й*^--^<:„ ;Г .t;> '| Не стоит огорчаться, задумываясь об объеме работы, необходимой для перевода данных, хранящихся в ре- реляционных базах данных, в объекты JavaScript или мас- массивы. Существует много способов создания такой ин- информации, которые исключают набор текста на клавиатуре. При частом изменении данных можно со- создать сценарий CGI или запустить другие серверные процессы, автоматически генерирующие код за счет экспорта таблицы баз данных. Создание поискового пользовательского интерфейса ¦Способ работы пользователей приложения с таблицей клиентской части зависит от определенного контекста приложения. В этом примере производится вызов поль- пользовательского интерфейса, в котором будет выполнять- выполняться поиск служащих на основе введенного текста. По- Поскольку таблица состоит из нескольких полей, можно предоставить пользователям большую свободу, обеспе- обеспечив поиск в четырех основных полях таблицы: FirstName, LastName, Title, Department. Предположим, что необходимо, чтобы результаты поиска были помещены в HTML-документ. Чтобы вы- вывести на экран одновременно определение поиска и результат, воспользуйтесь мулътифреймовъш окном. С учетом предоставленной ранее информации, определен список файлов, относящихся к телефонному списку: • employeelnfo.html — это родительское мультифрей- мовое окно, которое содержит базу данных со слу- служащими и другую глобальную информацию. • searchfrm.html — самый верхний фрейм, обеспечи- обеспечивающий пользовательский интерфейс для ввода по- поискового запроса. ¦• result.html — самый нижний фрейм, выводящий на экран результаты поиска. По умолчанию он пуст. На рис. 32.2 показан набор мультифреймовых окон приложения. Единственной частью интерфейса, с которой взаи- взаимодействует пользователь, является поисковое окно (searchfrm.html). Ниже представлен исходный код HTML для определения формы поиска в рамках окна: <body> <form method="POST" name="form"> <pre>Search By: </pre> <preXinput type=radio name=" searchBy" value="FirstName">First Name <input type=radio checked
Избранные программные технологии Часть V name="searchBy" value="LastName">Last Name <input type=radio name—"searchBy" value="Title">Title <input type=radio name="searchBy" value="Department">Department</pre> <pre>Text: <input type=text size=30 maxlength=30 name="searchByText"Xinput type=button size=20 name="findButton" Find onClick="doSearch () "Xinput type=reset name="Clear" value=" Clear " onClick="clearForm() "X/pre> </form> </body> атпда If,, ы., ** v- Intranet S**rch Ну: г First Нам Employee-' Database \ РИСУНОК 32.3. Пользовательский интерфейс поиска в базе данных. Обработка поисковых запросов Главной возможностью приложения, основанного на клиентских таблицах, является поиск данных. Напри- Например, в списке телефонов персонала необходимо опре- определить поле, по которому будет выполняться поиск, а затем передать эту информацию вместе с поисковым запросом в метод, реализующий собственно поиск. В данном примере обработка поиска проходит в двух местах. Метод doSearch() в фрейме searchForm подго- подготавливает поиск, а затем передает информацию в метод findEmployee() родительского окна. Чтобы проделать эту операцию, необходимо устано- установить метод doSearch() в качестве обработчика событий для кнопки Find. В этой функции выполняется проверка, какие переключатели отмечены и на основе этой инфор- информации производится установка значения переменной searchField. После проверки что в поле searchByText вве- введено какое-то значение, вызывается метод findEmployeeO родительского окна с передачей в него в качестве парамет- параметров переменной searchField и значения поля searchByText: function doSearch() { var searchField = " if (document.form.searchBy[0].checked) { searchField = "FirstName" } else { if (document.form.searchBy[1].checked) { searchField = "LastName } else { if ecked) ( searchField = "Title" } else { if (document.form.searchBy[35.checked) { searchField = "Department" ) :i i if (document.form. searchByText.value = null || document.form.searchByText.value == "") { alert("Please enter your search criteria before "¦continuing. ") } else { parent.findEmployee(searchField, document.form.searchByText.value) В родительском окне (employeelnfo.html) метод findEmployeeO получает эти два параметра и применя- применяет их при оценке массива объектов employee. Цикл for обеспечивает просмотр массива объектов employee, сравнивая значения поискового запроса (параметр searchWord) с определенным свойством (параметр searchField); при этом используется метод объекта стро- строки indexOf(). Перед тем как перейти к основному коду, рассмот- рассмотрим еще один пример. Если проводится поиск значения Richard в свойстве FirstName всех объектов, код будет выглядеть следующим образом: for (var i=l; i<empList. length; ) { if (empListfi] .FirstName. indexOf ( 'Richard'! '!= -1) { empListfl] .show() } Цикл for оценивает каждый объект и возвращает значение больше 0 при условии, если текст находится внутри значения свойства FirstName объекта employee. Если найдено необходимое соответствие, вызывается метод show() объекта employee. Этот метод будет под- подробно рассматриваться в одном из следующих разделов этой главы.
Технология обработки данных со стороны клиента А теперь, следуя той же логике, возьмемся вновь за список телефонных номеров. Примите во внимание: параметр searchField предназначен для представления имени свойства объекта, а не для строкового значения, поэтому придется воспользоваться встроенным методом evalQ. Метод eval() интерпретирует строковое значение и оценивает его как выражение JavaScript. Если преоб- преобразовать код JavaScript в отдельную строку, ее можно оценить с помощью метода eval(): function findEmployee(searchField, searchWord) { var str = "" ; // Здесь следует код форматирования for (var i=l; KempList. length; x++) ( str = "if (empList[" + i + "] ,." + searchField + ".indexOfC" + .searchWord + "') != -1) { empList[" + i + "] .show() }"; eval (str) ; II Здесь следует код форматирования Отображение результатов поиска Последний этап поискового процесса связан с представ- представлением результатов поиска пользователю. Для вывода информации на экран используется нижний фрейм (resultForm). Для этого можно усовершенствовать метод findEmployee, рассмотренный в предыдущем разделе. Для того чтобы HTML генерировался "на лету", не- необходимо воспользоваться объектом Document из result Form, который послужит "холстом" для записи. Снача- Сначала подготовьте холст документа с использованием ме- метода I)ocumentopen(). Затем, для отображения результа- результатов в табличном формате, можно создать таблицу HTML, через дескриптор <table> и установить заголовок таб- таблицы. window.resultForm.document.open(); window.resultForm.document.wri te( "<h2>Matches:</h2>"); window.resultForm.document.write( "<table border=l>"); window.resultForm.document.write("<trxtd wwidth=10%Xstrong>First. Name</strongX/td>") ,• window.resultForm.document.write("<td '-»width=15%Xstrong>Last Name</strongX/td>") ; window.resultForm.document.write("<td l~width=20%Xstrong>Title</strongX/td>") ; window.resultForm.document.write("<td b»width=15%Xstrong>Department</strongX/td>") ; window.resultForm.document.wri te("<td *->width=5%Xstrong>Ext.</strongx/td>"); window.resultForm.document.wri te("<td ^width=15%Xstrong>Email</strongX/tdX/tr>") ; Сейчас, когда все подготовительные действия завер- завершены, можно приступить к собственно обработке по- поиска. Каждый совпадающий служащий вызывается для Глава 32 выполнения метода show(). Этот метод применяется для вывода на экран информации как одной записи в таб- таблице. Поэтому потребуется добавить метод show() в конструктор объекта employee. function employee(FirstName, LastName, Title, Department, PhoneExt, EmailAddress) { this.FirstName = FirstName; this.LastName = LastName; this.Title = Title; this.Department = Department ; this.PhoneExt = PhoneExt; this.EmailAddress = EmailAddress; this.show = emp show; J После вызова метода show() объекта employee запус- запускается метод emp_show(), который определяет позиции для размещения форматируемого кода и вывода на эк- экран текущей информации о служащих. Для помещения значений каждого из свойств объекта в отдельные ячей- ячейки таблицы применяется метод write(): function emp_show(J ( window. resultForm. document .write ("<trxtd 1-»width=10%>" + this.FirstName + "</td>") ; window.resultForm.document.write("<td 1-»width=15%>" + this.LastName + "</td>"); window.resultForm.document.write("<td width=20%>" + this.Title + "</td>") window.resultForm.document.write("<td 4-»width=15%>" + this.Department + "</td>") ; window.resultForm.document.write("<td ^»width=5%>" + this. PhoneExt + "</td>") ; window.resultForm.document.write("<td width=15%>" + "<a href='mailto:" + this.EmailAddress + '">" + this.EmailAddress + "</tdX/tr>") ; j Обратите внимание, что для адресов электронной почты служащих определяется ссылка. Пользователю достаточно лишь щелкнуть на адресе служащего и со- сообщение будет отправлено. Последний код форматирования находится в мето- методе findEmployeeQ. После обработки всех записей служа- служащих, метод write() выводит дескриптор завершения таб- таблицы — </table>. Метод closeQ закрывает холст. Ниже показан полный исходный код метода findEmployeeQ: function findEmployee(searchField, var str = ""; searchWord) window.resultForm.document.open(); window.resultForm.document.wri te( "<h2>Matches:</h2>") ,- window.resultForm.document.write( "<table border=l>"); window.resultForm.document.write( "<trxtd width=10%Xstrong>First Name </strong></td>"); window.resultForm.document.write( "<td width=15%Xstrong>Last Name </strongX/td>") ; window.resultForm.document.write( "<tdwidth=20%Xstrong>Title</strong>
Избранные программные технологии Часть V window.resultForm.document.write( "<td width=15%Xstrong>Department </strongX/td>"); window.resultForm.document.write( "<td width=5%Xstrong>Ext. </strong> window.resultForm.document.write( "<td width=15%Xstrong>Email</strong> *-»</td></ tr>") ,- for (var i=l; i<=empList.length-1; i++) { str = "if (empList[" + i + "]." + searchField + ".indexOf(' " + searchWord + "') != -1) { empListp + i + "].show() }"; eval(str); 1 window. resultForm, document. write ( "</table>') ; window.resultForm. document.close О ; зан на рис. 32.4. Очистка поисковой формы и фрейма результатов осуществляется по щелчку на кнопке Clear. В листинге 32.1 представлен полный исходный код для родительского окна employeelnfo.html, а в листинге 32.2 — исходный код JavaScript для окна searchfrm.html. Запуск приложения Теперь можно протестировать приложение, загрузив в браузер файл employeelnfo.html. Предположим, что тре- требуется найти Грейди Андерсона (Grady Anderson). Вве- Введите Anderson в текстовое поле, выберите переключатель Last Name и щелкните на кнопке Find. Результат ПОКЙ- ЛИСТИНГ 32.1 employeelnfo.html Intranet Employee SAorch By; Г First ияыщ f lj.at )|«a# С titl* Matches ipirsl Naim iGrnily [Ciy' •Fnuik jierv ..... а' я_ LastiNamo iTltle ^Anderson .Trosramnic-r Anderson iSaJesperson iAnderson ^Salesperson Anderson i^rogrannner ¦"' SSSSriSs¦'¦ '¦ ¦¦•'-;¦ Database department (Sales' Sales " .. -_ь. „. — .,,4 Jem. 1198 [500 ilOO !1OO CinaU comi ¦:¦¦ Hilt!¦--¦¦ : HtL in-,-.- ¦¦¦¦¦ РИСУНОК 32.4. Результаты поиска, отображенные в виде таблицы. <html> <head> <title>Intranet Employee Database</title> <script language="JavaScript"> // Сетевая база данных по служащим / Глобальные var i = 1; var n = 1; переменные // Создание объекта Array var empList = new Array () ; employee // Метод show() — метод объекта function emp_show() { window.resultForm.document.write ("<trxtd width=10%>" window.resultForm.document.write("<td width=15%>" window.resultForm.document.write("<td width=20%>" window.resultForm.document.write("<td width=15%>" window.resultForm.document.write("<td width=5%>" window.resultForm.document.write("<td width=15%>" + this .FirstName + "</td>") + this.LastName + "</td>"); +• this.Title + "</td>") ; + this.Department + "</td>" *¦ this. PhoneExt + "</td>") + "<a href='mailto:" + this.KmailAddress + '">" + this.EmailAddress + "</tdx/tr>"> ; // Конструктор объекта employee function employee(FirstNami Title, Department, PhoneExt, EmailAddress) this. FirstName = FirstName; this.LastName = LastHame; this.Title = Title; this .Department = Department; this . PhoneExt = PhoneExt; this.EmailAddress = EmailAddress; this.show = emp_show; ¦ // Поиск служащего на основе поля и введенного слова
Технология обработки данных со стороны клиента Глава 32 function findEmployee(searchField, searchWord) var str = ""; window, resultForm. document, open () ; window. resultForm.document,write ("<h2>Matches:</h2>"); window.resultForm,document.write ("<tableborder=l>") ; window. resultForm. document, write ("<trxtd width=10%Xstrong>First Name</strongX/td>") ; window. resultForm, document, write ("<td width=15%Xstrong>Last Name</strongX/td>") ; window. resultForm. document.write ("<tdwidth=20%Xstrong>Title</strongX/td>") ; window. resultForm. document.write ("<tdwidth=15%Xstrong>Department</strongX/td>") ; window . resultForm. document . write ( "<tdwidth=5%Xstrong>Ext . </strongX/td>" ) ; window. resultForra.document.write ("<tdwidth=15%Xstrong>Email</strongX/tdx/tr>") ; for (var i=l; i<=empList.length-l; i++) { str = "if (empList[" + i + "]." + searchField + ".indexOf("' + searchWord +"') != -1) { empList[" + i + "] .show() } " ; eval(str); ) window, resultForm. document. write ( "</table>" > ; window, resultForm, document. close < } ; I // Создание объектов employee при запуске empList[l] = new employee ( "Richard", "Wagner", "Chief Technology Officer", "RSD", 00", "rwagner@acadians.com"); empList [2] = new employee ( "Grady" , "Anderson", "Programmer", "R&D", 98", "grady@acadians.com") ; empList[3] = new employee! '"Thomas", "Sprat", "Marketing Manager", "Marketing", 56", "tspratt@acadians.com "); empliiiit[4] = new employee ( "William", "Cleyball", "Marketing Manager", "Marketing", 51", "wcal@acadians.com ") ; empList[5] = new employee( "Fred", "Tortallini" , "Marketing Manager", "Marketing", 04", "tort@acadians.com ") ; empList[6] = new employee f "Smack", "Hopkins", "Marketing Manager", "Marketing", 06", "smack@acadians.com ") ; empList[7] = new employee ( "Luey", "Gentry", "Marketing Manager", "Marketing", 50", "luey@acadians.com ") ; empLi:3t[8] = new employee ( "Erwin", "Waltham" , "Marketing Manager", "Marketing", 45", "ew@acadians.com"); empList[9] = new employee С "Dallas", "Spanner", "Marketing Manager", "Marketing", 56", "dallas@acadians.com"); empList[10] = new employee( "Spill", "Hopkins", "Marketing Manager", "Marketing", 20", "spill@acadians.com ") ; empList[ll] = new employee( "Huey" , "Wagner", "Marketing Asst" , "Marketing", "854", "huey@acadians.com ") ; ¦empList[12] = new employee ( "Tom", "Longly" , "Marketing Asst", "Marketing", 12", "info@acadians.com ") ; empLi st[13] = new employee ( "Huck", "Starback", "Marketing Asst" , "Marketing", 12", "info@acadians.com "); empList[14] = new employee( "Crazy", "Lags", "Marketing Asst" , "Marketing", 22", "info@acadians.com ") ; empList[15] = new employee( "Bart", "Simpson", "Salesperson", "Sales", 00", "info@acadians.com"); empList[16] = new employee( "Bill", "O'Reilly", "Salesperson", "Sales", 00", "info@acadians.com"); empList[17] = new employee( '"Sally", "Smatterhorn" , "Salesperson", "Sales", 00", "info@acadians.com"); empList[18] = new employee( "Kim", "Pakki", "Salesperson", "Sales", 00", "info@acadians.com"); empList[19] = new employee) "Jacob", "Ladder", "Salesperson", "Sales", 00", "info@acadians.com"); empList[20] = new employee( "Jared", "Gaspe", "Salesperson", "Sales", 00", "info@acadians.com"); empList[21] = new employee( "Justus", "Argon", "Salesperson", "Sales", 00", "info@acadians.com"); empList[22] = new employee( "Jordan", "Basker", "Salesperson", "Sales", 00", "info@acadians.com"); empList[23] = new employee ( "Lisa", "Smith", "Salesperson", "Sales", 00", "info@acadians.com");
Избранные программные технологии Часть V empList[92] = new employee ( "Oil", "Larenzo", "Secretary", '"Company", "800", "info@acadians.com"); empList[93] = new employee ( '"Susie", "Que"r "Secretary", "Company", "800", "info@acadians .com") ; empList[94] = new employee ( "Trista" , "Wagner", "Secretary", "Company", "BOO", "info@acadians.com"); empList[95] = new employee ( "Kimberly" , "Smith", "Secretary", "Company", "800", "info@acadians.com"); empList[96] = new employee ( "Rachel", "McDonald", "Secretary", "Company", "800", "info@acadians.com"); empList[97] = new employee ( "Reena" , "Smiles", "Secretary", "Company", "800" , "info@acadians.com"); empList[98] = new employee ( "Treena", "Miles", "Secretary", "Company", "800" , "info@acadians.com"); empList[99] = new employee! "Corrina" , "Triles", "Secretary", "Company", "800" , "info@acadians.com"); empList[100] = new employee ( "Rosemarie", "Barlington" , "Secretary", "Company", "800", "info@acadians.com"); empList[101] = new employee ( "II", "Plage", "HR Manager", "Recruiting", "900", "info@acadians.com"); empList[102] = new employee { "Url", "Page", "HR Manager", "Recruiting", "900", "info@acadians.com"); empList[103] = new employee ( "Youri", "Basto", "HR Manager", "Recruiting", "900", "info@acadians.com"); empList[104] = new employee ( "Pri", "Opeo", "HR Manager", "Recruiting", "900", "info@acadians.com"); empList[10S] = new employee ( "Tikki", "Rodreguez" , "HR Manager", "Recruiting", "900", "info@acadians.com"); </script> </head> <?rameset rows=S% , 65%"> <frame src="searchfrm.html" name="searchForm" marginwidth=0" marginheight=0"> <frame name="resultForm" marginwidth=0" marginheight=0"> <noframes> Sorry, your browser does not support frames. </noframes> </frameset> <body> </body> </html> Листинг 32.2 searchfrm.html <html> <head> <title>Search Form</title> <script language="JavaScript"> // Сетевая база данных по служащем function doSearch ( ) ( var searchField = " " ; if(document, form.searchBy [ 0] .checked) { .searchField = "FirstName"; } ¦else { if (document.form.searchBy [1] .checked) ( .searchField = "LastNatne" ; } else { if (document.form. searchBy [2] .checked) { searchField = "Title" ; ) else { if (document.form.searchBy[3J .checked) { searchField = "Department"; }
Технология обработки данных со стороны клиента Глава 32 function findEmployee (searchField, searchWord) ( var str = ""; window. resultForm. document. open {) ; window, resultForm.dosument.write ("<h2>Matches:</h2>"); window. resultForm. docviment. wri te ("<tableborder=l>") ; window, resultForm. document, write ("<trXtdwidth=10%Xstrong>First Name</strongX/td>") ; window, resultForm. document, write ("<tdwidth=15%Xstrong>Last Name</strongX/td>") ,- window. result?orm,document.write ("<tdwidth=20%Xstrong>Title</strongX/td>") ; window. resultForm, document, write ("<tdwidth=15%Xstrong>Department</strongX/td>") ; window. resultForm,document.write ("<tdwidth=5%Xstrong>Ext.</strongx/td>") ; window. resultForm, document.write ("<tdwidth=15%Xstrong>Email</strongX/tdX/tr>") ,- for (var i=l; i<=empList.length-l; str = "if (empListf" + i + '•]." + searchField + ".indexOf('" + searchWord +"') != -1) { empList[" + i + "] .show() }"; eval(str); ) window, resultForm.document,write ("</table>"Jr window, resultForm. document. close ( ) ; i // Создание объектов employee при запуске empList[l] = new employee) "Richard", "Wagner", "Chief Technology Officer", "RSD", 00", "rwagner@acadians.com"); empList[2] = new employee ( "Grady" , "Anderson", "Programmer", "RSD", 98", "grady@acadians.com"); empLiKt[3J = new employee ( "Thomas", "Sprat", "Marketing Manager", "Marketing", 56", "tspratt@acadians.com ") ; empList[4] = new employee ( "William", "Cleyball", "Marketing Manager", "Marketing", 51", "wcal@acadians.com "); empList[5] = new employee ( "Fred1, "Tortallini" , "Marketing Manager", "Marketing", 04", "tort@acadians.com "); empList[6] = new employee ( "Smack", "Hopkins", "Marketing Manager", "Marketing", 06", "smack@acadians.com ") ; empList[7] = new employee ( "Luey", "Gentry", "Marketing Manager", "Marketing", 50", "luey@acadians.com ") ; empList[83 = new employee ( "Erwin", "Waltham" , "Marketing Manager", "Marketing", 45", "ew@acadians.com"); empList[9] = new employee ( "Dallas", "Spanner", "Marketing Manager", "Marketing", 56", "dallas@acadians.com"); empList[10] = new employee) "Spill", "Hopkins", "Marketing Manager", "Marketing", 20", "spill@acadians.com ") ; empList[ll] = new employee) "Huey", "Wagner", "Marketing Asst" , "Marketing", "854", "huey@acadians.com ") ; empList[12] = new employee( "Tom", "Longly", "Marketing Asst", "Marketing", 12", "info@acadians.com ") ; empList[13] = new employee) "Huck" , "Starback", "Marketing Asst" , "Marketing", 12", "info@acadians.com "); empList[14] = new employee) "Crazy", "Lags", "Marketing Asst1* , "Marketing", 22", "info@acadians.com ") ; empList[15] = new employee) "Bart", "Simpson", "Salesperson", "Sales", 00", "info@acadians.com"); empList[16] = new employee) "Bill", "O'Reilly", "Salesperson", "Sales", 00", "info@acadians.com"); empList[17] = new employee) "Sally", "Smatterhorn" , "Salesperson", "Sales", 00", "info@acadians.com"); empList[18] = new employee) "Kim", "Pakki", "Salesperson", "Sales", 00", "info@acadians.com"); empLi.st[19] = new employee) "Jacob", "Ladder", "Salesperson", "Sales", 00", "info@acadians.com"); empList[20] = new employee) "Jared", "Qaspe" , "Salesperson", "Sales", 00", "info@acadians.com"); empList[21] = new employee) "Justus", "Argon", "Salesperson", "Sales", 00", "info@acadians.com"); empList[22] = new employee) '"Jordan", "Basker", "Salesperson", "Sales", 00", "info@acadians.com"); empL:.st[23] = new employee) "Lisa", "Smith", "Salesperson", "Sales", 00", "info@acadians.com");
Избранные программные технологии Часть V empList[24] = new employeef "Cry", "Anderson", "Salesperson", "Sales", 00" , "info@acadians.com"); empList[25] = new employee) "Ollie", "Ryder", "Salesperson", "Sales", 00", "info@acadians.com"); ¦empList[26] = new employee( "Polly", "Potts", "Salesperson", "Sales", 00", "info@acadians.com"); empList[27] = new employee ( "Xerxes", "Srrdth", "Salesperson", "Sales", '-500" , "info@acadians.com"); empList[28] = new employee( "Sally Bae", "Srrdth", "Salesperson", "Sales'1, 00", "info@acadians.com") empList[29] = new employee( "Golden", "Driscoll", "Salesperson", "Sales", 00", "info@acadians.com") empList[30] = new employee( "Frank", "Anderson", "Salesperson", "Sales", 00", "info@acadians.com"); empList[31] = new employee( "Merv", "Anderson", "Programmer", "RSD", 00", "info@aeadians.com"); empList[32] = new employee( "Manu", "Waver", "Programmer", "RSD", 00", "info@acadians.com"); empList[33] = new employee) "Jason", "Driscoll", "Programmer", "RSD", 00", "info@acadians.com"); empList[34] = new employee) "Ardent", "Matthews", "Programmer", "RSD", 00", "infoSacadians.com"); empList[35] = new employee) "Ortho", "Dontal", " Prograrrmer", "RSD", 00", "info6acadians.com"); empList[36] = new employee) "Troy", "Smith", "Programmer", "RSD", 00", "info@acadians.com"); empList[37] = new employee) "Fred", "Barker", "Programmer", "RSD", 00", "info@acadians.com"); empList[3 8] = new employee) "Richini", "Barker", "Programmer", "RSD", 00", "info@acadians.com"); empList[39] = new employee) '"Ricardo", "Bollinger", "Programmer", "RSD", 00", "info@aoadians.com"); empList[40] = new employee) "Ron", "Bollinger", "Programmer", "RSD", 00", "info@acadians.com"); empList[41] = new employee) "Ronald", "Barker", "Programmer", '"RSD", 00", "info@acadians.com"); empList[42] = new employee) "Browser", "Tyler", "Programmer", "RSD", 00", "info@acadians.com"); empList[43] = new employee( "Serf", "Tyler", "Programmer", "RSD", 00", "info@acadians.com"); empList[44] = new employee) "Bill", "Tyler", "Programmer", "RSD", 00", "info@acadians.com"); empList[45] = new employee) "William", "Srrdth", "Programmer", "RSD", 00", "info@acadians.com"); empList[46] = new employee) "Billy", "Barker", "Programmer", "RSD", 00", "info@acadians.com"); empList[47] = new employee) "Kurt", "Barker", "Programmer", "RSD", 00", "info@acadians.com"); ¦empList[48] = new employee) "John", "Barker", "Programmer", "RSD", 00", "info@acadians.com"); empList[4 9] = new employee) "Jonathon", "Anderson", "Programmer", "RSD", 00", "info@acadians.com"); empList[50] = new employee) "Frederick", "Barker", "Programmer", "RSD", 00", "infofiacadians.com"); empListfSl] = new employee) "Smitty", "Tyler", "Programmer", "RSD", 00", "info@acadians.com"); empList[52J = new employee) '"Sargent", "Anderson", "Programmer", "RSD", 00", "infoSacadians.com"); empList[53] = new employee) "Pepe", "Potts", "Prograrrmer", "RSD", 00", "info@acadians.com"); empList[54] = new employee) "Leo", "Godfrey", "Programmer", "RSD" , 00", "info@acadians.com"); empList[55] = new employee) "Geo", "Stewart", "Programmer", "RSD" , 00", "info@acadians.com"); empList[56] = new employee) "Meo", "Anderson", "Programmer", "RSD", 00', "info@acadians.com"); empl4ist[57] = new employee) "Oeo", "Orefo", "Programmer", "RSD", 00", "info@acadians.com");
Технология обработки данных со стороны клиента Глава 32 empList[58] = new employee( "Jack", "Wagner", "Chief Entertainment Officer", "Exec", 00", "jwagner@acadians.com"); empList[59] = new employee ( "Brady", "Smith", "Programmer", "RSD", 00", "info@acadians.com"); empList[60] = new employee( "Tristin", "Ryder", "Programmer", "RSD", 00", "info@acadians.com"); empList[61] = new employee( '"James", "Tyler", "Programmer", "RSD", 00", "info@acadians.com"); empList[62] = new employee( '"Charles", "Potts", "Programmer", "RSD", 00", "info@acadians.com"); empList[63] = new employee! '"Bill", "Potts", "Senior Manager", "Management", 00", "info@acadians.com"); empList[64] = new employee ( "Bart", "Anderson", "Senior Manager", "Management", 00", "info@acadians.com"); empList[65] = new employee ( "Ian", "Potts", "Senior Manager", "Management", 00", "info@acadians.com"); empList[66] = new employee ( "Woody", "Smith", "Senior Manager", "Management", 00", "info@acadians.com"); empList[67] = new employee( "Mark", "Tyler", "Senior Manager", "Management", 00", "info@acadians.com"); empList[6S] = new employee ( '"Andrew", "Driscoll", "Senior Manager", "Management", 00", "info@acadians.com"); empList[69] = new employee ) "Andy", "Potts", "Senior Manager", "Management", 00", "info@acadians.com"); empList[70] = new employee ( '"Dandy", "Driscoll", "Senior Manager", "Management", 00", "info@acadians.com"); empList[71] = new employee ( '"Candy", "Potts", "Senior Manager", "Management", 00", "info@acadians.com"); ¦empList[72J = new employee ( "Spander", "Smith", "Senior Manager", "Management", 00", "info@acadians.com"); empList[73] = new employee ( "Landry", "Potts", "Senior Manager", "Management", 00", "info@acadians.com"); ¦empList[74] = new employee ( "Permy", "Smith", "Senior Manager", "Management", 00", "info@acadians.com"); empList[75] = new employee ( "Jostin", "Driscoll", "Senior Manager", "Management", 00", "info@acadians.com"); empList[76] = new employee( "Justin", "Ryder", "Senior Manager", "Management", 00", "info@acadians.com"); empList[77] = new employee) "Braxel", "Anderson", "Senior Manager", "Management", 00", "info@acadians.com"); empList[78] = new employee( "Opene", "Smith", "Senior Manager", "Management", 00", "info@acadians.com"); empList[79] = new employee) "Juan", "Barker", "Senior Manager", "Management", 00", "info@acadians.com"); empList[80] = new employee( "Julios", "Driscoll", "Senior Manager", "Management", 00", "info@acadians.com"); empLi:;t[81 ] = new employee! "Andre", "Barker", "Senior Manager", "Management", 00", "info@acadians.com"); empList[82] = new employee) "Bernard", "Smith", "Senior Manager", "Management", 00", "info@acadians.com"); empLii;t[83) = new employee) "Susan", "Ryder", "Senior Manager", "Management", 00", "info@acadians.com"); empList[84] = new employee) "Susanne", "Anderson", "Senior Manager", "Management", 00", "info@acadians.com"); empList[85] = new employee) "Chelsey", "Barker", "Senior Manager", "Management", 00", "info@acadians.com"); empList[86] = new employee) "Cosmo", "Krammer", "Senior Manager", "Management", 00", "info@acadians.com"); empList[87] = new employee) "Kirby", "Tipple", "Senior Manager", "Management", 00", "in?o@acadians. com") ; empLiiit[88j = new employee) "George", "Allen", "Senior Manager", "Management", 00", "info@acadians.com"); empLi!it[89] = new employee) "Boy", "Goeria", "Senior Manager", "Management", 00", "info@acadians.com"); empList[90] = new employee) "Teddy", "Washington", "Senior Manager", "Management", 00", "info@acadians.com"); empList[91] = new employee) "Tut", "Kingman", "Senior Manager", "Management", 00", "info@acadians.com"); 14 1-158
Избранные программные технологии ¦1Часть V empList[92] = new employee( ¦"Oil", "Larenzo", "Secretary", "Company", "800", "info@acadians.com"); empList[93] = new employee ( "Susie", "Que", "Secretary", "Company", "800", "info@acadians.com"); empList[94] = new employee ( "Trista", "Wagner", "Secretary", "Company", "800", "info@acadians.com"); empList[95] = new employee( "Kimberly", "Smith", "Secretary", "Company", "800", "info@acadians.com"); empList[96] = new employee( "Rachel", "McDonald", "Secretary", "Company", "800", "info@acadians.com"); empList[97] = new employee( "Reena", "Smiles", "Secretary", "Company", "800", "info@acadians.com"); empList[98] = new employee) "Treena", "Miles", "Secretary", "Company", "800", "info@acadians.com"); empList[99] = new employee( '"Corrina", "Triles", "Secretary", "Company", "800", "info@acadians.com"); empList[100] = new employee! "Rosemarie", "Barlington", "Secretary", "Company", "800", "info@acadians.com" empList[101] = new employee ( 1", "Plage", "HR Manager", "Recruiting", "900", "info@acadians.com"); empList[102] = new employee( "Url", "Page", "HR Manager", "Recruiting", "900", "info@acadians.com"); empList[103] = new employee ( "Youri", "Basto", "HR Manager", "Recruiting", "900", "info@acadians.com"); empList[104] = new employee( "Pri", "Opeo", "HR Manager", "Recruiting", "900", "info@acadians.com"); empList[105] = new employee) "Tikki", "Rodrequez", "HR Manager", "Recruiting", "900", "info@acadians.com") </script> </head> <frameset rows=S%,65%"> <frame src="searchfrm.html" name="searchForm" marginwidth=0" marginheight=0"> <frajne name="resultForm" marginwidth=0" marginheight=0"> <noframes> Sorry, your browser does not support frames. </noframes> < / frames e t > <body> </body> </html> Листинг 32.2 searchfrm.html <htrol> <head> <title>Search Form</title> <script language="JavaScript"> // Сетевая база данных по служащим function doSearch() { var searchField = "" ; if (document, form. searchBy [0] .checked) { searchField = "FirstName"; > else { if (document.form.searchByfl].checked) { .searchField = "LastName"; ) else ( if (document.form.searchBy[2].checked) ( searchField = "Title"; ) else ( if (document.form.searchBy[3].checked) { searchField = "Department"; }
Технология обработки данных со стороны клиента Глава 32 if (document.form.searchByText.value = null || document. form.searchByText. value = "") { alert ("Please enter your search criteria before continuing,"); } else { parent.findEmployee(searchField, document,form.searchByText.value) ; function clearForm() { parent.resultForm.do cument.open(> ; parent, resultForm document, close ( ) ; </scriptXhlXfont color="#000000"Xem>Intranet Employee Database</ernX/font> </hl> </head> <hr> <body bgcolor="#FFFFFF"> <form method="POST" name="form"> <pre>Search By: </pre> <C prexinput type=radio name="searchBy" value="FirstName">First Name <input type=radio checked name=" searchBy" value="LastName">Last Name <inpufc type=radio name=" searchBy " value="Title">Title <input type=radio name="searchBy" value="Department">Department</pre> <pre>Text: <input type=text size=30 maxlength=3 0 name=" searchByText" xinput type=button size=20 name="findButton" value=" Find " onClick="doSearch() "Xinput type=reset name="Clear" value=" Clear " onClick="clearForm () "X/pre> </form> </body> </html> Резюме Клиентские базы данных не могут служить в качестве замены SQL-серверов, и они не являются средством вво- ввода данных. Однако, несмотря на ограниченность диапа- диапазона их применения, внедрение баз данных в JavaScript приведет к расширению их возможностей и добавлению новых способов уменьшения нагрузки на сервер. Кли- Клиент может отвечать за поиск во всей базе данных и ви- визуализацию результатов. В главе рассматривались вопросы использования клиентских данных в качестве баз данных. Массивы JavaScript могут служить контейнерами баз данных, поиск которых реализуется при помощи встроенных конструкций языка JavaScript. Основа главы — практи- практический пример, в котором применение таблицы клиен- клиентской части стало идеальным вариантом.
Обработка ошибок В ЭТОЙ ГЛАВЕ Типы ошибок Интерпретация сообщений об ошибках Исправление кода Тестирование кода Программирование с использованием устойчивых технологий Надежная работа кода Обработка ошибок, вообще говоря, представляет собой комбинацию профилактического контроля (иден- (идентификация и исправление ошибок перед выполнением), пошагового контроля (идентификация ошибок в процес- процессе выполнения) и корректирующего контроля (исправле- (исправление ошибок, найденных во время выполнения). JavaScript (или более точно — интерпретатор JavaScript, встроен- встроенный в поддерживающие JavaScript браузеры), обеспечи- обеспечивает автоматизированный пошаговый контроль ошибок через диалоговые окна, отображающие информацию об ошибках. Освоение нового инструмента создания и от- отладки JavaScript-сценария помогает разработчику вос- воспользоваться преимуществом более автоматизированного профилактического и в меньшей степени — корректи- корректирующего контроля. В главе рассматриваются методы идентификации, исправления и тестирования JavaScript- кода, а также методы записи устойчивого и удобного в. сопровождении кода. Типы ошибок Ошибки JavaScript идентифицируются JavaScript-совме- JavaScript-совместимым браузером сразу же после загрузки HTML-стра- HTML-страницы. Эти ошибки можно разделить на три разных типа: Синтаксические ошибки Ошибки времени выполнения Логические ошибки 3ПРЕДОСГЕРЕЖЕНИЕ^Н^;, ' ,] _ ,/'*,.'' Интерпретатор JavaScript не идентифицирует логичес- логические ошибки. Для идентификации потенциальных ошибок в логике программы необходимо тестировать функци- функциональные возможности кода. Например, выполнение JavaScript-кода обязательно приведет к логической ¦ошибке при попытке выполнить арифметическое дей- действие над строковой переменной (позже это описыва- описывается более подробно; см. рис. 33.1). Синтаксические ошибки ¦Синтаксические ошибки, т.е. некорректная запись кода, часто связаны с банальными опечатками (не та буква, пропуск знака пунктуации, незакрытые скобки). Сле- Следующий пример демонстрирует несколько часто встре- встречающихся синтаксических ошибок: fuction errorProneO { // Слово "function" // записано неверно var i = о; // переменная инициализируется // буквой "о" вместо числа "О" for (i >= 0; I =< 10; i-t-t-) { // переменная "I" не определена (должна // использоваться строчная буква "i") document, write ("The square of " + i \ 11 is " + (i*i) + "<br>") // пропущена " ;" document.write ("The cube of " + i + 11 is ' + (i*i*i) + "<hr>") ; // требовались двойные кавычки li у/ отсутствует закрывающая фигурная скобка, J/ завершающая функцию ПРЕДОСТЕРЕЖЕНИЕ, „ X', . Язык JavaScript чувствителен к регистру, поэтому сле- следует быть внимательным при преобразовании букв в прописные. В частности, при использовании встроен- встроенных объектов JavaScript (а также их свойств, методов и событий) лучше убедится в точности синтаксиса с по- помощью Java ScriptLanguageReferenceGuidef Справоч- Справочник по языку JavaScript). Синтаксические ошибки в JavaScript — самые час- частые и самые простые в исправлении. JavaScript-интер-
Обработка ошибок Глава 33 ЕШ Претатор дает хороший результат по идентификации ис- источника этих ошибок в коде, и для их исправления не требуется ничего кроме простого редактирования. ПРИМЕЧАНИЕ Поскольку JavaScript имеет интерпретируемый харак- характер и в настоящее время не предлагает средств от- отладки синтаксиса, синтаксические ошибки идентифици- идентифицируют, запуская код на выполнение — т.е. загружая HTML-страницу, содержащую JavaScript, в JavaScript- браузер. г... .¦...¦...: .. .¦¦......:... ¦ .. "-¦¦¦-¦---¦»- Ошибки времени выполнения Ошибки времени выполнения возникают, если синтак- синтаксически корректный оператор пытается выполнить за- задачу, реализовать которую невозможно. К довольно- таки обычным ошибкам времени выполнения относятся недопустимые вызовы функций, несоответствие типов данных, присваивание значения необъявленной пере- переменной и арифметически некорректные операции (та- (такие как деление на ноль). Об ошибках времени выполнения браузер выдает сообщение, аналогичное сообщениям о синтаксических ошибках; однако, их исправление часто требует более тщательного изучения кода. Следующий пример пока- показывает ошибку времени выполнения программы, выз- вызванную делением на ноль: function mismatched() { var i = 10; for (i. <=10; i >= 0; i—) { // этот цикл вызовет деление на ноль // и результаты будут непредсказуемыми document.write (i + " divided by twice its square (" + (i*i*2) +¦¦)="+ (i/(i*i*2)) 1 Логические ошибки Логические ошибки происходят, когда приложение или функция не исполняют то, на что ее ориентировали пользователи или разработчики. Другими словами, при- приложение, которое имеет синтаксически корректный код и не содержит ошибок времени выполнения, но все еще выдает некорректные результаты, содержит логические ошибки. Логические ошибки — самый трудный для идентификации и исправления тип ошибок. Они обыч- обычно требуют серьезного тестирования приложения, ана- анализа результатов и пересмотра всего проекта. Множество логических ошибок возникает из-за плохого понимания требований, некачественного проектирования и, как результат — некорректного кода. Следующий пример демонстрирует логическую ошибку, вызванную вычис- вычислением несогласованных типов данных: function mismatched () { var Constant = 0"; var i = 10; for (i <= 10; i > 0; i— document.write(i + " + ' + (i + Constant) н Constant Как видно из рис. 33.1, отображаемые результаты явно неправильны, даже при том, что код выполнился успешно. В этом случае JavaScript вычисляет результат выражения (i + Constant) как строку и выполняет кон- конкатенацию двух операндов. Is this correct? 10 + 10- 1010 9+10= i 8 + 10 810 7 + 10 710 6 + 10 = 610 ' 5 + 10^510 4 + 10=410 3 + 10 = 310 2 + 10=210 1 + 10 = 110 : ^Ш«ИЯ РИСУНОК 33.1.Логическая ошибка. Интерпретация сообщений об ошибках Как только браузер распознает ошибку (синтаксическую или времени выполнения), он отображает большое ди- диалоговое окно, как показано на рис. 33.2. Информация, содержащаяся в таких диалоговых окнах, помогает идентифицировать вероятный источник и расположе- расположение ошибки. Диалоговое окно содержит следующую информацию: URL или имя файла, в котором произошла ошибка. Номер строки в файле, где произошла ошибка. Это порядковый номер строки от начала HTML- (или JS-) файла, а не только JavaScript-кода. Не очень-то по- полагайтесь на достоверность такой информации, по- поскольку источник ошибки может находиться и в со- совершенно другом месте. • Описание ошибки. Вот это, как раз, ценная инфор- информация в плане идентификации типа требуемого ис- исправления. Фактический код, содержащий ошибку. Эта инфор- информация тоже не всегда будет надежной, т.к. источник ошибки может находится и до этой строки.
Избранные программные технологии Часть V i Указатель места в строке, где произошла ошибка. На эту информацию также нельзя слишком полагаться; попытайтесь исследовать близлежащий код. i missing } t Err». ok] N •i:\\nui'i2.JitnK line 16: ¦ .... РИСУНОК 33.2. JavaScript-сообщение, уведомляющее о синтаксической ошибке. В табл. 33.1 приводится описание большинства ти- типичных JavaScript-сообщений об ошибках и их возмож- возможные причины. Исправление кода Даже при том, что сообщения об ошибках полезны для идентификации многих ошибок программы, обычно требуется проделать дополнительную поисковую рабо- работу для исправления всех ошибок, особенно логических. Этот раздел покажет, как упростить и систематизиро- систематизировать поисковую работу подобного рода. В главе 34 бу- будет обсуждаться использование отладчика JavaScript компании Netscape. Проверка кода HTML Поскольку JavaScript обычно взаимодействует с HTML- кодом, прежде всего необходимо удостовериться, что файл не содержит ошибок HTML. Ниже приводится список, который можно рассматривать в качестве руко- руководства по нахождению таких ошибок: Проверьте открывающие и закрывающие дескрипто- дескрипторы <script>. Проверьте атрибут language = "JavaScript" внутри пары дескрипторов <script>. Проверьте HTML-дескрипторы на предмет пропус- пропусков или орфографических ошибок. Проверьте угловые скобки (< >), открывающие и закрывающие дескриптор. Проверьте связанные пары дескрипторов (например, <script>...</script>). Проверьте корректность использования дескрипто- дескрипторов HTML-комментариев (<! — ... — >), скрываю- скрывающих JavaScript-сценарий. • Удостоверьтесь, что имена форм и фреймов, вызы- вызываемых в JavaScript-коде, соответствуют именам, оп- определенным в HTML-файлах. ПРВДОеТЕРЕЖЕНИЕ Если требуется размещать JavaScript-код в пределах HTML-таблицы, непомещайтедескрипторы<8спр?>во внутренние ячейки таблицы (<td> ... </td>). Это — известная ошибка JavaScript, которая обычно приводит к зависанию браузера. Вместо этого разместите дес- дескрипторы <script> внутри необходимыхопределений строк таблицы (<fr> ... </tr>) и создайте определе- определение HTML-ячеек (<td> ... </td>) с помощью мето- метода document.writel). Использование комментариев для идентификации проблем Можно воспользоваться комментариями для последова- последовательного выделения различных строк (и функциональных возможностей) кода, чтобы таким образом идентифици- идентифицировать и установить источник ошибок. Это многошаго- многошаговый процесс. Таблица 33.1. Типичные JavaScript-сообщения об ошибках. Сообщение об ошибке Возможные причины item is not defined item is not a function item cannot be converted to a function item has no properties item is not a numeric literal 'Unterminatedstring literal missing ) after argument list (и аналогичные сообщения об ошибках) Названная переменная не определена. Имя переменной содержит орфографические ошибки. Названная функция не определена. Незавершенная строка (рассматривается JavaScript как неопределенная переменная). Функция не определена. Функция с орфографической ошибкой. Перед определением функции возникли другие ошибки. Переменная ошибочно упоминается как вызываемая функция. Имя функции (или метода встроенного объекта) содержит орфографическую ошибку. Некорректная ссылка на свойство объекта. Некорректная ссылка на массив. Переменная не содержит числовых данных. Перед присваиванием переменной значения присутствуют другие ошибки. Отсутствие кавычек (для строки). Строка содержит более 250 символов. Строка содержит символ новой строки. Пропущена круглая скобка, фигурная скобка или точка с запятой.
Обработка ошибок В приведенном ниже списке указаны шаги, которые потребуется предпринять: Закомментируйте одну или большее количество строк кода. Сохраните код. Перегрузите страницу в браузере. • Запомните полученный эффект. • Измените код или закомментируйте большее коли- количество строк. Повторяйте перечисленные шаги, пока не найдете ошибку. Использование метода alert() для трассировки кода Для идентификации некоторых ошибок времени выпол- выполнения и большинства логических ошибок в коде нужно уметь следовать за логикой кода и представлять, как он обрабатывает данные. Многие средства отладки позво- позволяют выполнять код пошагово, по одной строке в каж- каждый момент времени, и в боковом окне (под названием "окно отладки") просматривать результат выполнения кода. Для моделирования такой среды отладки можно воспользоваться JavaScript-методом alert(). Метод alert() отображает диалоговое окно, которое можно легко запрограммировать на показ различных полезных со- сообщений и значений, помогающих последовательно отслеживать выполнение кода. В главе 34 проводится упражнение по отладке, использующее только методы alert(). Рассмотрим некоторые способы применения метода alert(): Используйте alert(" Starting Check") для идентифи- идентификации отправной точки отладки. По мере выполне- выполнения отладки его можно перемещать далее по коду. ¦• Используйте а1ег1()для отображения значений пере- переменных, массивов и возвращений функций. С помо- помощью простых тестовых сценариев можно быстро оп- определить, соответствуют ли отображенные значения ожидаемым. • ИспользуйтеакгК) для отображения результатов вы- выражений. Это особенно полезно для отслеживания логических ошибок, поскольку причиной многих ло- логических ошибок является некорректное использова- использование выражений. Тестирование кода Глава 33 помощью JavaScript, — за исключением того, что ваше "производство" — мирового масштаба со множеством потенциальных пользователей и разными платформами. С учетом всего этого для проверки JavaScript-кода нужно использовать множество различных методов тестирова- тестирования. Потребуется проделать некоторый (небольшой) объем модификаций, дабы удовлетворить требования мира JavaScript и Internet. JavaScript — язык програм- программирования, приспособленный для создания сложных приложений, поэтому, как и в случае традиционных языков программирования, он требует надежного тес- тестирования. 'ПРИМЕЧАНИЕ Тестирование — это не то же самое, что отладка. Те- Тестирование — это средство обнаружения ошибок. От- Отладка — средство определения источника ошибок и ис- исправления их. Традиционное тестирование кода подразумевает, что приложение готовится к производству. Эта концепция ¦будет верна и в том случае, когда речь идет о помеще- помещении в Internet Web-страниц, усовершенствованных с При тестировании кода обязательно следует предпо- предполагать, что ошибки в программе присутствуют. Если предположить, что ошибок в коде нет вообще, скорее всего, ни одна ошибка не будет найдена! Практически, даже наиболее полное тестирование никогда не сможет доказать отсутствие ошибок (для подобного доказатель- доказательства пришлось бы выполнить бесконечное количество тестов); можно только доказать существование ошибок. Для того чтобы упростить работу по тестированию кода, стоит подготовить формальный план тестирова- тестирования, который должен содержать как контрольный спи- список (одностраничный список всех высокоуровневых действий по тестированию), так и детальные тестовые сценарии для проверки кода. Тестовые сценарии долж- должны содержать список определенных и систематических испытательных шагов, которые требуется выполнять в приложении, а также ожидаемые результаты. При про- проектировании тестовых сценариев необходимо учиты- учитывать: ¦• Требования для приложения. Необходимо удостове- удостовериться, что приложение удовлетворяет исходным функциональным требованиям. Тестирование должно включать также и получение ответа от пользователя (или заказчика) о том, насколь точно функциональ- функциональность приложения соответствует первоначальным требованиям. Ответ пользователей относительно ос- основной модели приложения поможет провести иден- идентификацию и исправление многих логических оши- ошибок, обусловленных выполнением не тех требований. • Требования по дизайну. Необходимо удостоверится, что приложение соответствует предложенному дизай- дизайну. Это тестирование должно включать получение ответа от дизайнеров приложения о том, насколь точно приложение соответствует их проекту. Это те-
Избранные программные технологии Часть v стирование также может помочь идентифицировать потенциальные недостатки проекта. Шаблоны потоков данных. Необходимо проверить корректность потока данных в системе, особенно ка- касающихся дизайна. Это тестирование должно прове- проверить целостность данных, обрабатываемых приложе- приложением. Необходимо составить схему потока данных в приложении от ввода до обработки для пошагового отслеживания воздействий на данные. Функции. Необходимо проверить каждую функцию в приложении на предмет корректной реализации функциональных возможностей. Это тестирование должно проверять правильность функциональных возможностей отдельных функций независимо от ос- остальной части кода. Успех этого тестирования часто зависит от того, насколько модульными (сосредото- (сосредоточенными на одной цели, независимыми) являются функции. (Модульное программирование рассматри- рассматривается более подробно позже в этой главе, в разделе "Написание модульного кода.") Строки программы. Необходимо протестировать каж- каждую строку приложения на предмет проверки кор- корректной реализации функциональных возможностей. Это может быть сделано путем пошагового прохода по строкам программы и проверки результатов вы- выполнения этих строк (для изоляции кода можно вос- воспользоваться комментариями). Плохие данные. Необходимо также проследить, как приложение выполняется при получении плохих данных (например, недостаточно данных, слишком много данных, неправильный тип данных или раз- размеры данных). Это тестирование должно также про- проверять поведение приложения, когда требуемые или необязательные данные отсутствуют (например, пу- пустые поля ввода в форме). Тестирование должно подтвердить существование методов обработки оши- ошибок, справляющихся с такими ситуациями. Краевой анализ. Необходимо проследить, как прило- приложение исполняется при указании краевых данных, циклов и итерационных вызовов функций. Это тес- тестирование должно гарантировать, что приложение будет правильно обрабатывать минимальные и мак- максимальные значения переменных, а также что име- имеется в наличии встроенный метод обработки ошибок для значений, которые приложение не может обра- обработать. Наиболее частые значения. Необходимо проследить, как приложение исполняется, когда получает инфор- информацию, чаще всего вводимую пользователем. Это тестирование должно гарантировать, что приложение работает безупречно для обычных данных, поскольку его неудачная работа затронет большинство пользо- пользователей. Наиболее частые ошибки. Проверьте, что наиболее частые или выявленные ранее ошибки исправлены. Тестирование должно гарантировать, что ошибки, исправленные ранее, в дальнейшем не возникнут снова в более поздней версии кода. Самая вероят- вероятная причина такого типа ошибок — плохое управле- управление изменениями (или управление версиями), что может потребовать последующих тестирований этих процедур с целью идентификации и исправления ошибок. • Различные платформы. Протестируйте приложение на различных аппаратных и программных платфор- платформах. В Internet присутствует огромное число пользо- пользователей, работающих с различными аппаратными (такими как Intel, Macintosh и Sun) и операционны- операционными системами (Windows 95, Windows 98, Windows NT и разновидности UNIX и Linux). Создаваемый код лучше протестировать на как можно большем ко- количестве различных платформ, чтобы хорошо пони- понимать его поведение и, в случае необходимости, из- изменять его. ¦• Минимальные конфигурации. Протестируйте прило- приложение на клиентских рабочих станциях с минималь- минимальными конфигурациями. Напомним, что пользовате- пользователи располагают различными ресурсами. Необходимо выяснить, какое количество требований приложение предъявляет машине клиента (например, в терминах мощности обработки, памяти, пропускной способно- способности). Это поможет понять, какой должна быть ми- минимальная конфигурация аппаратной и программной платформы, на которой данное приложение будет выполняться успешно. Тестирование должно вклю- включать проверку выполнения кода для рекомендуемых минимальных конфигураций, а также обработку ошибокдля пользователей, имеющих конфигурацию меньше минимальной. • Различные браузеры. Протестируйте приложение в различных браузерах, поддерживающих JavaScript. Это тестирование поможет увидеть обработку со- созданного кода различными браузерами, а также со- совместимость кода. Если совместимость кода отсут- отсутствует, можно либо изменить существующий код либо написать дополнительный код обработки оши- ошибок. ¦• Совместимость HTML со старыми браузерами. Не- Необходимо гарантировать, что HTML-файл сможет читаться в старых (неподдерживающих JavaScript) браузерах. Проверьте работу кода в текстовых или старых браузерах, чтобы выяснить, как отсутствие JavaScript повлияет на пользовательскую среду —
Обработка ошибок например, браузер может подвиснуть или войти в аварийный режим, или страница может просто не загрузиться. Проверьте, доступен ли альтернативный путь чтения содержимого сайта и насколь он эффек- эффективен и надежен. В многих случаях из-за требований наличия определен- определенных функциональных возможностей имеет смысл со- сознательно проектировать и реализовывать сайт для браузеровопределенногобазового(ил и минимально- минимального) уровня. Например, можно потребовать, чтобы пользователь имел по крайней мере Navigator 4.7 или Internet Explorer 4.0 для эффективной работы с при- приложением. В таком случае необходимо сообщить пользователям об этих требованиях до того, как они зайдут на сайт, и предоставить гиперссылки на стра- страницы, где они смогут выгрузить соответствующие бра- браузеры. Альтернативное решение — можно написать JavaScript-сценарий для выяснения типа браузера, и если он не соответствует минимальным требованиям, отображать предупреждающее сообщение либо авто- автоматически отсылать пользователя к соответствующе- соответствующему сайту загрузки браузера. В главах 26 и 27 можно найти более подробную информацию о таких JavaScript- кодах . • Перегрузка. Проверьте поведение приложения при перезагрузке HTML-страницы. Это тестирование должно подтвердить, что при перезагрузке код ведет себя правильно. Если перезагрузка воздействует на код, то тестирование должно подтвердить существо- существование кода обработки ошибок и команд, помогаю- помогающих пользователю избежать проблем. • Изменение размеров. Проверьте поведение приложе- приложения при изменении размеров окна браузера. Это те- тестирование должно подтвердить, что при изменении размеров код ведет себя правильно. Если это изме- изменение воздействует на код, то тестирование должно подтвердить существование кода обработки ошибок и команд, помогающих пользователю избежать про- проблем. .ПРИМЕЧАНИЕ ' :;': V <:,-,... Х'ТХ*?Л'Г *.-¦¦ '"''" '-к^ При изменении размеров окна Netscape Navigator текущая Web-страница перегружается. Microsoft Internet Explorer только изменяет размеры окна без перегрузки текущей Web-страницы. Испытания в утяжеленном режиме (стресс-тест). Проверьте поведение приложения в момент, когда им пользуются сразу много людей. Это тестирование можно провести при наличии нескольких пользова- пользователей, выполняющих данный код, следуя определен- определенному и детально разработанному сценарию, либо за Глава 33 счет применения некоторой автоматической пуско- пусковой возможности. Необходимо выполнить монито- мониторинг, запись и анализ результатов всех испытаний (в том числе время ответов и сбои поведения). Необхо- Необходимо также выяснить, как тестируемый код влияет на остальную часть сайта. В случае необходимости измените код и проведите повторное тестирование. Потеря связи. Проверьте поведение приложения в момент сбоя Internet-соединения либо остановки заг- загрузки страницы. Пользователи обычно теряют связь с сайтом или вручную останавливают передачу дан- данных. Код должен при необходимости изящно справ- справляться с этим (избегая подвисания браузера и его аварийного завершения). Проверьте наличие соответ- соответствующих функциональных возможностей. С0ВЕТ "" ' .;':'„Д;*л..' V,-*,i/. ,. .*„....' #J Netscape Navigator имеет встроенный URL, который можно использовать для быстрой проверки строк JavaScript-кода. В окне URL браузера Navigator введите javascript*, код на JavaScript, (mocha: кол на JavaScript выполняет аналогичный тест.) Например, при вводе javascript: alert|"Hello World!") в диалоговом окне alertП отображается строка Hello World. Программирование с использованием устойчивых технологий Как и любые другие программисты, авторы JavaScript- кодов могут извлечь большую пользу из изучения и использования при написании кода приложений устой- устойчивых технологий программирования. Даже при том, что JavaScript все еще слишком молод, чтобы иметь богатый собственный материал по упомянутым техно- технологиям, можно воспользоваться хорошим набором об- общих рекомендаций, существующим в других (особенно объектно-ориентированных) языках программирования. Следующий список показывает некоторые из методов,, адаптированных под JavaScript: • Высокоуровневая разработка кода проекта и деталь- детальное проектирование. • Написание модульного кода. • Написание сильно связанного кода. Написание слабо связанного кода. Написание повторно используемого кода. Написание кода обработки ошибок. • Использование жестких соглашений по именованию. Использование комментариев. • Объявление и инициализация переменных.
Избранные программные технологии Часть V Каждый из перечисленных методов кратко объясня- объясняется в следующих разделах. Однако, не следует забы- забывать, что последовательное выполнение таких методов требует подробного изучения, не только из-за уровня требуемой дисциплины, но также и для того, чтобы избавиться от некоторых плохих привычек и взамен приобрести хорошие привычки! Высокоуровневая разработка кода проекта и детальное проектирование Это первый шаг на пути создания качественного кода. Высокоуровневая разработка поможет идентифициро- идентифицировать типы функциональных возможностей, требуемых для различных функций приложения. Детальное про- проектирование поможет идентифицировать и вызвать от- отдельные функции и составить схемы их процессов. Хороший детальный проект (особенно, если он на- написан на псевдокоде) можно без особых трудностей преоб- преобразовать в код и комментарии. Необходимо по крайней мере уметь записывать объявления функций и перемен- переменных непосредственно из проекта. Кроме того, следует уметь итеративно разбивать оставшуюся часть детально- детального проекта на подразделы и преобразовывать каждый из этих подразделов в код. Написание модульного кода Написание мбдульного кода означает разделение при- приложения на несколько отдельных функций (или моду- модулей), где каждая функция исполняет только одну зада- задачу и связывается с другими функциями с помощью вызовов. Такое модульное кодирование выгоднее по следующим соображениям: • Уменьшение сложности. Каждый модуль сосредото- сосредоточен только на одной задаче, следовательно, большин- большинство модулей остаются простыми. ¦• Уменьшение дублирования. Если один и тот же тип функциональных возможностей требуется в несколь- нескольких местах, соответствующий код будет написан только один раз (в функции). • Уменьшение степени влияния изменений. Можно из- изменять часто используемые функциональные воз- возможности только в одном месте (в функции, где они постоянно содержатся) вместо изменений в несколь- нескольких местах. • Увеличение степени сокрытия процесса. Детали вы- выполнения функций скрываются от других функций. Это означает, что можно изменять способ работы функции без изменения остальной части кода (под- (поддерживая один и тот же интерфейс функции). Увеличение степени повторного использования кода. Можно повторно использовать отдельные функции в других программах, требующих того же типа фун- функциональных возможностей. • Улучшение удобочитаемости. Модульное програм- программирование приводит к более простым и совершен- совершенным компонентам, которые, в свою очередь, делают программу более удобочитаемой и легко сопровож- сопровождаемой. Написание сильно связанного кода Связность зависит от того, насколь близкими являются задачи функции. Сильно связанный код означает, что функция почти полностью ориентирована на достиже- достижения одной цели. Она должна достигать только одной цели и делать это хорошо. Пример такой функции — Math.S(pt(value). Эта функция просто вычисляет квад- квадратный корень значения, которое получает в качестве аргумента, и возвращает результат. Сильная связность ведет к высокой надежности, поскольку выполняемые задачи каждой функции очень узко определены, а количество этих задач — очень ог- ограничено. Написание слабо связанного кода Связность зависит от того, насколь близко соотносятся две функции. Слабо связанный код означает, что отно- отношения между двумя функциями слабые, видимые и прямые. Это обеспечивает для любой функции возмож- возможность вызова другой функции, и при этом независи- независимость от другой в реализации своих собственных фун- функциональных возможностей. Написание повторно используемого кода Модульное программирование помогает в создании по- повторно используемого кода. По сути дела, этот код (или функцию) можно включать в любой другой код с целью обеспечения тех же функциональных возможностей. Написание подобного рода кода дает множество выгод: Высокая надежность. Повторно используемые фун- функции доказаны и проверены множество раз. • Низкая стоимость. Не возникает потребности в реа- реализации новой функции. Мобильность. Можно легко сделать код доступным для других платформ. Сокрытие информации. Внутренние операции кода скрыты от вызывающих объектов. Написание кода обработки ошибок Качественная программа должна быть способна не толь- только предвидеть необычные и ошибочные события (на- (например, некорректные данные, необычное поведение пользователя или прерывание передачи), но также и справляться с ними как можно более изящно. Это тот
Обработка ошибок Глава 33 случай, когда хорошо написанный код обработки оши- ошибок становится жизненно важной проблемой. Обработ- Обработка ошибок должна быть встроена в код и выполнять, по крайней мере, некоторые из перечисленных ниже задач: ¦ • Проверять значения всех вводимых данных из вне- внешних источников. Необходимо проверить правиль- правильность данных, включая типы, диапазон значений и завершенность ввода. Если здесь происходит ошиб- ошибка, программа должна сбросить текущие данные и запросить отправку новых. Проверять значения всех параметров функций. Не- Необходимо проверять правильность данных, получен- полученных из других функций. В случае ошибки получаю- получающая функция должна сбросить ошибочные данные и отправить новый запрос к передающей функции. • Выполнять обработку исключений. Исключения дол- должны замечаться программой и регистрироваться в протоколе исключений. Если решение конкретного исключения не существует, функция должна краси- красиво завершиться. Проверять другие важные ошибки. По возможности, код обработки ошибок должен предотвращать появ- появление ошибок. • Выполнять изящное завершение. Если сбои кода или пользователь остановят передачу файла до того, как страница полностью загрузится, браузер должен ос- остаться в рабочем состоянии (т.е., он не должен за- зависнуть или аварийно завершиться). Это можно сде- сделать, написав подпрограмму обработки ошибок, проверяющую, загружена ли страница успешно, или же открывая новое окно браузера для приложения, чтобы в случае возникновения аварийной ситуации она затронула бы только его собственное окно. Использование жестких соглашений по именованию Использование жестких соглашений по именованию означает применение соответствующих, согласованных и значимых имен для всех объявлений (например, объяв- объявлений объектов, свойств, методов и переменных) в коде. Жесткие соглашения по именованию помогают упрос- упростить сопровождение кода, улучшить удобочитаемость, увеличить ясность кода и устранить рост числа конф- конфликтующих имен (когда тот же самый объект вызыва- вызывается с помощью двух разных имен). В коде можно использовать множество способов раз- разработки жесткого соглашения по именованию. Ниже приведен список того, что лучше отчетливо выделить в коде: Глобальные переменные ¦• Локальные переменные • Поименованные константы ¦• Имена функций ¦• Аргументы функций совет ' '"./ '-' '-''", V- '/ ;, ;: Используйте отформатированные составные слова для расширения смысла и удобочитаемости имен. Напри- Например, воспользуйтесь MaximumWeight = 200 для пере- переменной или findHeightlnMeters(Height) {... — для фун- функции. Использование комментариев Комментарии могут оказаться очень эффективной фор- формой связи исходного кода, написанного программистом, с остальной частью мира, в том числе и с другими про- программистами, которые, возможно, будут поддерживать код позже. Насколько хороший комментарий увеличи- увеличивает удобочитаемость программы, настолько же плохой комментарий может мешать и вводить в заблуждение. Для написания полезных комментариев требуется осто- осторожность и внимание. Ниже приводятся некоторые ре- рекомендации для написания хороших комментариев: • Поместите в комментарии важную информацию о программе с выходными данными (например, авто- автором, датой последней модификации, целью функций и последних изменениях). Они могут оказаться един- единственным доступным или актуальным источником документации. Напишите комментарии о коде, который трудно по- понять с ходу. Комментарии должны добавить смысл, чтобы пользователь понял больше, чем уже очевид- очевидное. . Напишите комментарии о предназначении кода, объясняющие, почему что-то делается. Это означает, что комментарии следует помещать в соответствую- соответствующие места (например, перед или после строки про- программы) для объяснений целей и способов работы кода. ¦ • Напишите комментарий по глобальным переменным. Что они содержат? Когда они были изменены? ¦• Напишите комментарий для нетривиальной или за- запутанной части кода. Что она делает? Почему ис- используется? ¦• Помните, что те, кто будет загружать данную Web- страницу, могут увидеть JavaScript-комментарии, просто в браузере просматривая исходный код HTML,, так что не стоит помещать в JavaScript-комментариях информацию, не предназначенную для чужих глаз.
Избранные программные технологии Часть V Объявление и инициализация переменных Несмотря на то что JavaScript позволяет использовать необъявленные и неинициализированные переменные в коде, хорошая практика программирования предпола- предполагает последовательное объявление и инициализацию переменных. Объявление переменных в одном общем для всех месте (обьгано в начале функциональной или глобальной области) делает отслеживание и поддержа- поддержание их относительно простым делом. Инициализация переменных гарантирует, что переменные содержат корректный тип данных в любом месте программы. (Например, если var Counter = 0;, это значит, что пе- переменная Counter имеет числовой тип данных.) Не используйте в качестве имен переменных зарезер- зарезервированные ключевые слова JavaScript — это приводит к ошибкам. Загляните в справочник по JavaScript для выяснения списка зарезервированных ключевых слов. Надежная работа кода JavaScript, подобно другим языкам программирования, имеет свои нюансы — включая ошибки языка, неясные особенности и странное поведение — которые потребу- потребуется изучить перед написанием действительно устойчи- устойчивого кода. Необходимо также знать различия между реализацией JavaScript в Netscape Navigator и JScript (реализация JavaScript от Microsoft) в Microsoft Internet Explorer. Даже при том, что они в основном идентич- идентичны, каждая из них обладает такими функциональными возможностями, которыми не обладает другая. Вместо того чтобы исписывать страницу за страницей, внося в список ошибки, туманные особенности и странные моменты поведения различных браузеров только для того, чтобы выяснить, что они были установлены в последней версии кода, стоит лишь подчеркнуть, что JavaScript (и, следовательно, JScript) — все еще разви- развивающийся язык. Это означает, что нужно знать уровень браузера(ов), которые выбираются для обеспечения базовых (или минимальных) требований к сайту, а так- также отличия этих браузеров от других версий. Для получения списка последних наиболее извест- известных ошибок JavaScript и методики их обработки мож- можно посетить страницу Netscape JavaScript Known Bugs no адресу http://developer.netscape.com/support/bugs/ known/. Актуальная информация по JScript находится на страни- странице Scripting Technologies по адресу http://nisdn.inicrosoft.coni/ scripting/default. htm?/scripting/jscript/. В случае если необходимая информация не найде- найдена ни на одном из упомянутых сайтов, стоит поучаство- поучаствовать в конференциях, посвященных JavaScript (напри- (например, в телеконференции comp.Iang.javascript в Usenet). Наконец, чтобы значительно повысить шансы на хоро- хорошее написание кода, работающего в обоих браузерах, следует убедиться, что код протестирован в обоих бра- браузерах и не использует такой JavaScript-код, который работает в одном браузере и не работает в другом. Резюме Глава была посвящена анализу трех типов ошибок Java- JavaScript (синтаксические, ошибки времени выполнения и логические) и представила стандартные JavaScript-сооб- JavaScript-сообщения об ошибках, а также об их возможных причинах. Кроме того, рассматривались способы исправления кода и идентификации ошибок. Также обсуждался си- систематизированный подход к тестированию кода, состо- состоящий из плана тестирования и детализации тестовых сценариев, а также определенные пункты создания сце- сценариев тестирования. Были продемонстрированы способы формирования и предварительного контроля кода (с целью уменьше- уменьшения времени на отладку) с апробированными методами реализации устойчивого и удобочитаемого кода. Эти методы в конечном счете помогают сохранить многие часы рабочего времени и качественнее спроектировать код. В заключение в главе были кратко представлены некоторые из последних ошибок JavaScript и способы их обработки, обеспечивающие надежное функциони- функционирование кода.
Отладка В ЭТОЙ ГЛАВЕ Использование отладчика сценариев Microsoft Использование JavaScript-отладчика Netscape Использование метода alert() Хотя отладку исходного кода зачастую не относят к элементам программирования, ее можно назвать базо- базовым элементом создания приложений в любом языке программирования. Не исключением является и JavaScript. Теперь, когда JavaScript нашел свое место в семей- семействе кодов, мы, наконец, получили среду со всесторон- всесторонней поддержкой средств написания и отладки сценариев, аналогичную таковой в зрелых языках программирова- программирования (C++, Visual Basic и Java). Эти инструментальные средства можно отнести к следующим трем категориям: Инструменты интегрированной среды разработки (Integrated Development Environment — IDE). Они помогают быстро создавать функциональные и дина- динамические Web-сайты, в том числе страницы, исполь- использующие JavaScript. • Инструменты написания JavaScript-сценариев. Они помогают более эффективно разрабатывать страни- страницы с JavaScript с помощью интуитивно понятного визуального интерфейса и технологий редактирова- редактирования. Примером такого инструмента может служить Infuse Acadia. • Инструменты отладки JavaScript-сценариев. Они по- помогают более эффективно выполнять отладку, ис- исправление и тестирование кода с использованием графического интерфейса и стандартных методов от- отладки (типа точек останова и пошагового выполне- выполнения). Примером такого инструмента может служить JavaScript Debugger от Netscape. Появление новых инструментов создания и отладки JavaScript-сценариев обеспечивают разработчикам воз- возможность пользоваться преимуществами более автома- автоматизированных предварительных и (в меньшей степени) корректирующих средств контроля. Если доступ к JavaScript-средствам отладки отсутствует, либо объем работы по отладке достаточно невелик, то в качестве средства отладки можно применять простое сигнальное окно JavaScript. В этой главе рассматриваются три дос- доступных варианта отладки JavaScript-кода, которые все- всегда имеются в распоряжении. Использование отладчика сценариев Microsoft Отладчик сценариев Microsoft (Microsoft Script Debugger, MSSD) — свободно выгружаемое средство отладки сце- сценариев, которое работает как интегрированная часть Internet Explorer (в версиях 3.01 и выше). MSSD можно использовать для написания и, что более важно, для отладки кода JavaScript (JScript в исполнении Microsoft) или Visual Basic Script (VBScript). Преимущество MSSD заключается в его в способности обрабатывать требова- требования отладки ActiveX, Java, JScript и VBScript. (MSSD можно выгрузить из сайта http://msdn.microsoft.com/ scripting/.) Обзор возможностей отладчика сценариев Microsoft Ниже приведены основные возможности отладчика сце- сценариев Microsoft: • Динамическое представление структуры HTML. Как видно из рис. 4.1, MSSD позволяет рассматривать полную структуру страницы в окне Project Explorer, a отдельные HTML-файлы (например, для фреймов) - в специально выделенных окнах. • Многоязыковая интеграция. Можно выполнять от- отладку JavaScript, VBScript и Java в одном и том же документе.
Избранные программные технологии Часть V F.<i-m:. П?Г : .¦:.:¦¦¦¦•;/:.:¦:; ; .- ..: Ш 'Ш '.'¦'¦¦ ¦¦¦¦: ¦:¦¦¦¦¦¦¦ ¦¦ ¦¦¦:¦.:.¦ ..-.._ :¦:. . ¦ •: •¦• . ^й! -' --'I ¦.•.4-:.;,:a,::.!--,:~:L,i.:.ii. ib-.Ji;, : ii '.i : V:,.. .,. - .ДЙ8ЯВДИ1ИМ|Д1М РИСУНОК 34.1. Просмотр HTML-файлов в отладчике сценариев Microsoft. • Выделение цветом синтаксиса. MSSD отображает код со стандартными цветами отладки, что помогает луч- лучше идентифицировать состав кода и упрощает про- процесс отладки. Точки останова. Можно проставлять точки останова в любых местах сценария, обеспечивая останов вы- выполнения отладки. • Пошаговое выполнение кода. MSSD позволяет поша- пошагово (с паузами после каждого шага) выполнять код — по одной строке на каждом шаге. • Пошаговое выполнение блоков кода. Позволяет по- пошагово выполнять код, но при этом процедуры вы- вызываются как один модуль (без пошагового выполне- выполнения кода внутри них), и переходить к следующему оператору. • Пошаговое выполнение кода внутри блоков. В отли- отличие от пошагового выполнения блоков кода, здесь выполняются остающиеся строки (начиная от точки выполнения) вызванной процедуры, и затем про- программа переходит на следующий после вызова дан- данной процедуры оператор. • Интегрированный стек вызовов. MSSD интегрирует стеки вызс IB (как VBScript, так и Script) в коде в один стек вызовов. • Окно непосредственного выполнения выражений. Это окно позволяет быстро вычислять выражение в пределах стека вызовов либо тестировать новый код. Окно отображает результат выполнения строки про- программы. Использование отладчика сценариев Microsoft для отладки файлов В этом разделе пошагово демонстрируется пример се- сеанса отладки в MSSD. В течение этого сеанса макси- максимальное внимание будет уделяться возможностям MSSD и их применению, и в меньшей степени — содержимо- содержимому и функциональности примера. Предполагается, что в качестве браузера используется Microsoft Internet Explorer (версии 3.01 и выше), а также наличие установ- установленного MSSD. Запуск отладчика сценариев Microsoft Единственный способ запуска MSSD предполагает пер- первоначальное открытие Internet Explorer и загрузку в него необходимого исходного HTML-файла. Затем можно активизировать MSSD, выбрав View ' Source (Вид -» Источник). ПРИМЕЧАНИЕ : Если MSSD не установлен, то выбор View - откроет исходный файл в редакторе Notepad. Для запуска процесса отладки выберите Edit Break at Next Statement (Правка • Останов на следующем операторе) в Internet Explorer (или же Debug > Break at Next Statement (Отладка • Останов на следующем опе- операторе) в MSSD) и запустите сценарий. Отладчик за- запускается и останавливается на первом операторе теку- текущего сценария. Использование команды "Break at Next Statement Команда "Break at Next Statement" (которая присутствует в опции "Script Debugger" меню "View" (Вид) в [i Explorer и меню "Debug" (Отладка) в MSSD) аналогич- аналогична команде выполнения шага (при которой отладчик выполняет один оператор в сценарии и затем останав- останавливается), за исключением того, что ее можно также использовать без запуска сценария. Это важная особенность отладки MSSD, поскольку 'большое количество JavaScript-кода обычно объявляет- объявляется в разделе заголовка (или <HEAD>) HTML-файла, и эта команда представляет собой единственный способ отладки такого кода. Так происходит потому, что код в заголовочном раздела файла к моменту загрузки HTML- файла уже выполнен (вспомните, что JavaScript — ин- интерпретируемый язык). Кроме того, любой набор точек останова, загруженных после HTML-файла, при пере- перегрузке страницы теряется. Вычисление выражений Выражение можно вычислить в окне непосредственно- непосредственного вычисления (окно Im •} MSSD, а также с ис- использованием следующих двух методов: • Debug.write(string). Этот метод записывает указан- указанную строку (обычно значение переменной) в окно Immediate без пробелов и символов новой строки между строками.
Отладка • Debug.writeln([string]). Этот метод идентичен преды- предыдущему за исключением того, что после каждой строки вставляется символ новой строки. Аргумент строки здесь необязателен. Если он не указан, в окно Immediate записывается только символ новой стро- строки. На рис. 34.2 показан пример использования окна Immediate для вычисления выражений (или значений переменных). РИСУНОК 34.2. Использование окна Immediate для вычисления выражений. Разбор примера Для более четкого понимания возможностей MSSD необ- необходимо попрактиковаться в использовании его для от- отладки кода. Следующее упражнение дает хорошую от- ную точку для такой тренировки: Откройте Internet Explorer. 2. Выберите Edit > Break at Next Statement. 3. Откройте HTML-файл, приведенный в листинге 34.1. Для этого можно набрать его URL, перетащить файл в окно браузера либо воспользоваться пунктом меню File -» Open. В этом файле потребуется заме- заменить имена WAV-файлов на имена и пути звуковых файлов, доступных в вашей системе: Листинг 34.1. Использование JavaScript-события для воспроизведения звука. <html> <head> <title>Sound on JS events</title> <script language="javascript"> <! - - Скрыть код от старых браузеров function playSound(sfile) { // Загрузка и воспроизведение звукового файла window.location, href=sfile; Глава 34 // Конец сокрытия —> </script> <body onLoad="playSound('Type.wav');" onUnLoad="playSound('Glass.wav');"> <font size=+2>Sounds on JS Events</font> <br> <hr> The following are example of JS event handlers used to play sounds. <hr> <a href="#" onClick="playSound('Cashreg.wav');"> Click here for sound</a> <brxbr> <form name="forml"> <input type="button" value="Press Button to play a sound" onClick="playSound('Gunshot.wav');"> </form> </body> </html> 4. Когда файл открыт, активизируется MSSD, и пос- после выполнения первого оператора происходит оста- останов, как показано на рис. 34.3. РИСУНОК 34.3. Останов MSSD после чтения первого оператора. 5. Теперь можно пошагово проходить код, чтобы уви- увидеть последовательность действий программы. Для пошагового прохождения кода используются пик- пиктограммы инструментальной панели Step Into, Step Over и Step Out. Рис. 34.4 показывает следующую строку программы, которая выполняется при нажа- нажатии на кнопку "Step Into". СОВЕТ Названия пиктограмм инструментальной панели MSSD можно увидеть, поместив на них курсор мыши и не выполняя щелчок одну-две секунды. Более детальное описание всех пиктограмм и возможностей MSSD на- находится в справочной системе. - . . ... . : ,н ; ... 6. После перехода (возможно, при помощи пиктограм- пиктограммы Continue) к завершению вызова события onLoad,
Избранные программные технологии Часть V можно будет услышать звуковой файл, который за- запустит система (если компьютер имеет соответству- соответствующие аудиовозможности). Возможно, потребуется явно разрешить браузеру открывать звуковой файл, в зависимости от конфигурации Internet Explorer. Эта мера принимается для защиты от открытия не- неизвестного и потенциально опасного (содержащего вирус) не-НТМЬ-файла. На рис. 34.5 показан файл после его полной загрузки в браузер. РИСУНОК 34.4. Прохождение кода с использованием пиктограмм инструментальной панели MSSD. 3 are ехв РИСУНОК 34.5. Результат загрузки кода излистинга 34.1. 7. Выберите Edit * Break at Next Statement для оста- останова выполнения кода после следующего операто- оператора. Щелкните на кнопке Press a Button to Play a Song на HTML-странице. Отладчик остановится на обра- обработчике событий onClick. Можно теперь отслежи- отслеживать вызовы процедур, открыв окно Call Stack (Стек вызовов), как показано на рис. 34.6, и пошагово выполняя код. . Можно также просматривать значения выражений или строк программы (не пустых и не строк ком- комментариев) в окне Immediate: 1. Щелкните из MSSD внутри функции playSound в коде (это первая функция, объявленная в заго- заголовке). 2. Если попытаться напечатать что-нибудь внутри функции, MSSD отобразит панель с вопросом, потребуется редактировать документ. Щелкните на Yes и напечатайте Debug.writeln (sfile); прямо перед фигурной скобкой (}), закрывающей фун- функцию. 3. Сохраните отредактированный файл, используя File Save (Файл Сохранить) (или нажав на пиктограмму Save в инструментальной панели). РИСУНОК 34.6. Использование окна Call Stack для отображения активных вызовов процедур. 4. Можно также проставить вручную точку остано- останова в строке Debug. Нажмите F9 для установки (или снятия) точки останова. (Строка точки ос- останова выделяется красным цветом и слева от нее проставляется красная точка.) 5. Теперь переключитесь на браузер и обновите (пе- (перегрузите) HTML-файл. (Помните, что в таком случае набор точек останова теряется, поэтому, если требуется остановить код на определенной строке, нажмите F9 для добавления точки оста- останова в MSSD.) 9. Когда файл начнет выполняться, откройте окно Immediate в MSSD для визуализации текущего со- содержания выражения Debug. Если продолжить по- пошаговое прохождение кода, можно заметить, что содержимое окна Immediate модифицируется каж- каждый раз при вызове функции Debug.writeln (см. рис. 34.7).
РИСУНОК 34.7. Использование MemodaDebug.\mte\nu вычисление выражения в окне Immediate. Заключительные слова об отладчике сценариев Microsoft Отладчик сценариев Microsoft обеспечивает полезную среду для автоматизированного выполнения отладки и тестирования JavaScript-кода. Инструменты MSSD очень похожи на инструменты, которые обычно присутству- присутствуют в средах зрелых языков программирования, таких как Visual Basic и C++. К тому же, интерфейс, установка и инсталляция MSSD являются интуитивно понятными и дружественными к пользователю. Однако, MSSD обладает и некоторыми ограничени- ограничениями, например, в процессе отладки требуется часто переключаться между Internet Explorer и MSSD, и нет возможности вывода печать исходного кода. Если необ- необходимо большее количество функциональных возмож- возможностей, чем может предложить MSSD, обратитесь к Microsoft Visual InterDev 6.0. Эта программа реализует все перечисленные здесь возможности отладки сценари- сценариев плюс зрелую среду для Web-разработки. Наконец, MSSD — это инструмент, который стоит иметь в своем арсенале; кроме того, важно, что он рас- распространяется свободно. Однако, он никоим образом не заменяет запись устойчивого кода и систематическое его тестирование. Использование JavaScript-отладчика Netscape Как и отладчик сценариев Microsoft, JavaScript-отлад- JavaScript-отладчик Netscape — свободно распространяемое средство отладки JavaScript, которое работает как интегрирован- интегрированная часть Netscape Navigator. (Его можно выгрузить из сайта http://devedge.netscape.com/software/tools/ index, html.) Отладка Глава 34 Исследование возможностей JavaScript- отладчика Netscape Ниже перечислены основные возможности JavaScript- отладчика Netscape: Окно Source View (Исходный код). Позволяет про- просматривать исходный код отлаживаемой HTML-стра- HTML-страницы. ¦• Прерывание. Позволяет останавливать выполнение кода отладчиком в любой момент времени. Точки останова. Позволяет вставлять точки остано- останова в любые места сценария для приостановки отлад- отладчика в этих точках. • Пошаговое выполнение кода. MSSDiiO3bojihct поша- пошагово (с паузами после каждого шага) выполнять код — по одной строке за шаг. • Пошаговое выполнение блоков кода. Позволяет по- пошагово выполнять код, но при этом процедуры вы- вызываются как один модуль (без пошагового выполне- выполнения кода внутри них), и переходить к следующему оператору. • Пошаговое выполнение кодов внутри блоков. В от- отличие от пошагового выполнения блоков кода, здесь выполняются остающиеся строки (начиная от точки выполнения) вызванной процедуры, и затем про- программа переходит на следующий оператор после вызова данной процедуры. • Окно Console (Консоль). Обеспечивает область для визуализации вычислений JavaScript-выражений активного в данный момент фрейма. Инспектор объектов. Позволяет просматривать и ра- работать со значениями свойств объекта. • Окно наблюдения. Позволяет просматривать выраже- выражения каждый раз, когда интерпретатор останавливает и активизирует отладчик. • Окно Call stack (Стек вызовов). Отображает располо- расположение текущей команды. • Диалоговое окно Error Reporter (Генератор отчетов об ошибках). Отображает информацию о синтаксичес- синтаксических ошибках и ошибках времени выполнения в JavaScript-коде. Использование JavaScript-отладчика Netscape для отладки файлов В этом разделе пошагово демонстрируется пример се- сеанса отладки в JavaScript-отладчике Netscape. Предпо- Предполагается, что в качестве текущего браузера используется Netscape Navigatorc установленным JavaScript-отладчи- JavaScript-отладчиком Netscape.
Избранные программные технологии Часть V Запуск JavaScript-отладчика Netscape Для того чтобы открыть исходный HTML-файл для отладки его в JavaScript-отладчике Netscape, необходи- необходимо выполнить следующие шаги: 1. Начните с загрузки страницы JSDebugger.html, рас- расположенной в каталоге Netscape\Communicator\ Program\JSDebug, и нажмите на ссылку для запус- запуска отладчика. 2. В браузере Navigator откройте страницу, которую требуется отлаживать. 3. С помощью кнопки Open (Открыть) в инструмен- инструментальной панели отладчика выберите страницу из списка страниц, открывшихся в Navigator после запуска отладчика. Страница отобразится в окне Source View. 4. Установите в отладчике желаемый набор точек ос- останова. .5. Щелкните на кнопке Reload (Обновить) в Netscape Navigator для запуска отладки страницы. ПРИМЕЧАНИЕ При любой остановке JavaScript-отладчика Netscape применение браузера Netscape Navigator для просмот- просмотра Web-страниц невозможно. Разбор примера Для более глубокого понимания возможностей JavaScript- отладчика Netscape неплохо потренироваться в практи- практическом использовании его для отладки кода. Следующее упражнение обеспечивает хорошую отправную точку: I. Откройте HTML-файл, показанный в листинге 34.2, напечатав соответствующий URL в Netscape Navigator. Откройте тот же файл в JavaScript-отлад- JavaScript-отладчике Netscape. Листинг 34.2. Отображаемый код. <html> <title>vehiele_test.html</title> <body> <script language="JavaScript"> //Объявление двух глобальных переменных дпя // описания транспорт) > средства var vehicleColor; var vehicleType; ипа транспортного средства function setType() < return(vehicleType="truck"); //Установка цвета транспортного средства function setColor() ) return(vehicleColor="blue"); //Уведомление пользователя, если тип и цвет // транспортного средства не установлены // корректно. if(setType() II setColor ()) ' + vehicleType + " is ' + vehicleColor) else alert("The vehicle type and color could not ^be set") ; </script> </body> </html> 2. После открытия и запуска файла полученная в результате Web-страница должна иметь вид, по- показанный на рис. 34.8. С первого же взгляда мож- можно понять, что возникли некоторые проблемы. Предполагалось, что сценарий должен установить тип транспортного средства в truck с помощью фун- функции setType() и его цвет — в blue с помощью фун- функции setColor(). Если эти две функции работают должным образом, строка должна выводиться на экран; в противном случае отображается сигнальное сообщение, говорящее, что одна из операций при- присваивания потерпела неудачу. В данном случае сиг- сигнальное сообщение не было отображено, но все же переменная, представляющая цвет транспортного средства, не получила значение blue. РИСУНОК 34.8. Результат загрузки листинга 34.2. 3. Поскольку нас интересуют значения переменных vehicleType и vehicleColor, добавим эти две перемен- переменные в список наблюдения в отладчике. 4. Для начала остановите отладчик, щелкнув на пик- пиктограмме Interrupt (Прерывание). Обновите окно Netscape Navigator, чтобы начать отладку. 5. Начните пошаговое прохождение кода программы строка за строкой, щелкая на пиктограмме Into. Пос- После выполнения каждой строки контролируйте зна- значения двух переменных, которые появляются в окне Console (Консоли). Прежде чем отладчик дойдет до оператора if, можно будет заметить, что обе пере- переменные не были определены, как следовало бы ожидать. После оператора if отладчик перейдет на
Отладка- функцию setType() (если продолжать щелкать на пиктограмме Into). После перехода на функцию setType() переменная vehicleType устанавливается в truck. В этой точке планировался переход на функ- функцию setColor(), но вместо этого программа перехо- переходит на метод document.write() (см. рис. 34.9). Что же заставило оператор if пропустить вызов функции se1:Color()? Более детальное исследование операто- оператора if показывает, что первый аргумент в логической операции OR вычисляет true, после чего второй аргумент не вычисляется вообще. Поскольку функ- функция setType() вернула true, функция setColor() вы- выполнятся уже не будет. Для коррекции проблемы следует просто заменить логическую операцию OR на логическую операцию AND. Правильная версия сценария показана в листинге 34.3. Результат выпол- выполнения файла представлен на рис. 34.10. Глава 34 return(vehicleColor="blue"); //Уведомление пользователя, если тип и цвет // транспортного средства не установлены // корректно. if(setType() && setColor()) + vehicleColor) ; I else + vehicleType + " is alert("The vehicle type and color could not ^>be set") ; </script> </body> </html> Vl-п- return(vehiclcCoJ.Qr-'*blueB); 21:J 22: alevc(The vehicle type end color cuui i oar, ttfc э«"): Ш I РИСУНОК 34.9. JavaScript-отладчик Netscape после выполнения действия. Листинг 34.3. Исправленный код. <html> <title>vehicle_correct.html</title> <body> <script language="JavaScript"> //Объявление двух глобальных переменных для // описания транспортного средства var vehicleColor; var vehicleType; //Установка типа транспортного средства function setType() i return (vehicleType="truck") ,¦ //Установка цвета транспортного средства function setColor() niiL? The truck is blue я РИСУНОК 34.10. Результат загрузки листинга 34.3, Заключительные слова о JavaScript- отладчике Netscape JavaScript-отладчик Netscape обеспечивает полезную среду для автоматизированного проведения отладки и тестирования JavaScript-кода. Инструменты JavaScript- отладчика Netscape очень похожи на инструменты, обычно имеющиеся в средах зрелых языков программи- программирования, таких как Visual Basic и C++. Интерфейс, ус- установка и инсталляция JavaScript-отладчика Netscape интуитивно понятны и дружественны к пользователю. ¦Однако JavaScript-отладчик Netscape обладает и ря- рядом ограничений. Среди наиболее значимых ограниче- ограничений — необходимость частого переключения между Netscape Navigator и JavaScript-отладчиком Netscape в процессе отладки, а также невозможность создания, изменения и вывода на печать исходного кода. Использование метода alertf) Если вам не доступен полный набор возможностей JavaScript-отладчикалибо вы ограничены во времени и не хотите запускать JavaScript-отладчик для решения простой проблемы, связанной с функциональностью,
Избранные программные технологии Часть V можно найти и другой выход. То, кто когда-либо созда- создавал программу на каком-либо языке программирования, тот знает, что один из наиболее простых и самых быс- быстрых способов отладки проблем функциональности — это отображение значений основных переменных на раз- различных стадиях выполнения программы. Таким спосо- способом можно выяснить, выполняется ли код так, как было задумано. В JavaScript есть удобный метод под названием alert(), который может приостанавливать выполнение сценария с целью визуализации значения переменной. Немного поразмыслив и надлежащим образом разместив этот метод, можно быстро отследить проблемы функцио- функциональных возможностей в сценариях. Разбор примера Для того чтобы проиллюстрировать использование ме- метода alertQ для отладки JavaScript-кода, возьмем тот же самый сценарий, который использовался в примере с JavaScript-отладчиком Netscape (см. листинг 34.3), что- чтобы можно было затем сравнить эти два метода. 1. Откройте JavaScript-браузер. 2. Откройте HTML-файл листинга 34.2, напечатав его URL в Netscape Navigator. 3. После открытия и запуска файла получившаяся в результате Web-страница должна иметь вид, пока- показанный на рис. 34.8. С первого же взгляда видно присутствие некоторых проблем. Предполагалось, что сценарий должен устанавливать тип транспорт- транспортного средства в truck с помощью функции setType() и его цвет — в blue с помощью функции setColor(). Если эти две функции работают должным образом, строка должна выводиться на экран; в противном случае отображается сигнальное сообщение, говоря- говорящее, что одна из операций присваивания потерпе- потерпела неудачу. В данном случае сигнальное сообщение не было отображено, но все же переменная, пред- представляющая цвет транспортного средства, не полу- получила значение blue. 4. Поскольку нас интересуют значения переменных vehicleType и vehicleCoIor, отобразим значения этих двух переменных в вызовах alert(). Необходимо ак- аккуратно поместить методы alert() в точки кода, что поможет точно определить проблемную область. Например, метод alert() B каждой из устанавлива- устанавливающих переменные функций может уведомить, чтс» функция была выполнена. Метод alert() до и после оператора if сообщит, как вычисляется условное выражение. Загрузите в браузер код из листинга .34.4, который содержит эти дополнительные мето- методы alert(). Листинг 34.4 Отладка с использованием alert(). <html> <title>vehicle_debug.html</title> <body> <script language="JavaScript"> //Объявление двух глобальных переменных для // описания транспортного средства var vehicleColor; var vehicleType; //Установка типа транспортного средства function setType () i_l alert("Inside the setType function."); //Оператор отладки return<vehicleType="truck") ; J //Установха цвета транспортного средства function setColor() '{ alert("Inside the setColor function."); //Оператор отладки return(vehicleColor="blue">; .! //Оператор отладки alert("Before if statement: type="+vehicleType+" color="+vehicleColor); //Уведомление пользователя, если тип и цвет // транспортного средства не установлены // корректно, if (setType () | | setColor ()) t //Оператор отладки alert("After if statement: type="+vehicleType+" color="+vehicleColor); document.write("The ' + vehicleCoIor) ; vehicleType else alert ("The vehicle type and color could not set") ; </script> </body> </html> Убедитесь, что каждый вызов alert(J содержит доста- достаточно информации, чтобы можно было выяснять мес- место остановки в коде только за счет чтения текста в сиг- сигнальном окне., 5. Когда файл открыт и запущен, посмотрите, какие сигнальные окна отображены и какие — нет, а так- также — каковы значения переменных на каждом эта- этапе выполнения. Первое отображаемое сигнальное окно показывает, что обе переменные не были ой-
Отладка ределены перед выполнением оператора if, как и ожидалось. Следующее сигнальное окно показыва- показывает, что функция setType() была выполнена. И пос- последнее сигнальное окно отображает набор типов транспортных средств truck, но цвет после операто- оператора if все еще не определен, как видно из рис. 34.11, Что же случилось с функцией setColor()? Метод ali;rt() в функции setColor(), которая не была вы- выполнена, сообщает, что функция setColor() не была вызвана в операторе if. Ясно, что проблема — в опе- операторе if. РИСУНОК 34.11. Результат загрузки листинга 34.4. 6. Более детальное рассмотрение оператора if показы- показывает, что первый аргумент в логической операции OR вычисляется как true, в результате чего второй аргумент не вычисляется вообще. Поскольку функ- функция setType() вернула true, функция setColor() уже не будет выполнятся. Для исправления проблемы надо просто заменить логическую операцию OR на логическую операцию AND. He забудьте удалить методы alert(), которые были добавлены для целей отладки. Правильная версия сценария приведена в листинге 34.3. Результат выполнения файла показан на рис. 34.10. Глава 34 ПРВДО-ГЕРЕЖЕНЙЕ Не забудьте удалить методы alertf), которые были добавлены для целей отладки. Итоговые слова об использовании метода alert() Как было показано выше, метод alcrt() может оказать- оказаться удобным средством отладки для быстрого решения небольших проблем с функциональностью. При отлад- отладке сложных проблем с функциональностью либо про- проблем с синтаксисом метод alert() будет больше мешать, нежели помогать в плане экономии времени. При всей своей полезности метод alertQ не должен рассматри- рассматриваться в качестве альтернативы полнофункциональных средств отладки наподобие JavaScript-отладчика Netscape. Резюме В глава были представлены три средства отладки JavaScript-кода. Отладчик сценариев Microsoft и JavaScript- отладчик Netscape позволяют отлаживать сложные JavaScript-коды. Оба инструментальных средства стоит поместить в свой арсенал средств, и важно помнить, что распространяются они совершенно бесплатно. Хотя об этом не упоминалось в данной главе, на рынке присут- присутствует множество других инструментальных средств отладки с полным набором возможностей, однако зача- зачастую они стоят достаточно дорого. В последней части главы рассматривалось применение сигнальных окон как дополнительного средства отладки, когда нет дос- доступа к средствам отладки Netscape или Microsoft. Но даже с этими новыми инструментальными средствами ответственность за полное тестирование и отладку JavaScript-кода лежит на разработчике. Ни одно из средств отладки, обсужденных в этой главе, не может заменить написание устойчивого кода и систематичес- систематическое его тестирование.
JavaScript и безопасность в Web В ЭТОЙ ГЛАВЕ Концепции безопасности в клиентской части JavaScript Максимизация надежности защиты Концепции безопасности в серверной части JavaScript Java и безопасность JavaScript предоставляет разработчику Web-сайта возможность расширять статические HTML-страницы с помощью динамического, управляемого событиями языка программирования. Web-страница с JavaScript- кодом обеспечивает интерактивные функциональные возможности, выполняя фрагменты JavaScript-кода в кли- клиентском Web-браузере. Включение фрагментов JavaScript- кода в страницу документа требует принятия мер по защите как целостности кода интерпретатора сценари- сценариев браузера, так и самого сценария. Просмотр страни- страницы, поддерживающей JavaScript, подвергает пользова- пользователя большей опасности, нежели выполнение чистого HTML-документа, поскольку из-за выполняемых фраг- фрагментов кода возникает еще один уровень сложности в программе браузера. В случае традиционного программного обеспечения между пользователем и программным обеспечением существует четкие соглашения. Установка и использо- использование программ требует от пользователей явных дей- действий и решений. JavaScript-код не соответствует при- принятым соглашениям. Код сценария загружается из удаленного источника и выполняется без подтвержде- подтверждения пользователя. Выполнение непроверенного кода из удаленного источника аналогично поеданию яблока, по- полученного по почте от неизвестного отправителя. В ис- исполняющую JavaScript-код систему должны быть поме- помещены определенные проверки и ограничения, дабы уберечь компьютер пользователя от преднамеренных или неумышленных посягательств на ценную информа- информацию и приложения. Ни один пользователь не захочет предоставить всему миру доступ к своему компьютеру, поэтому знания особенностей JavaScript-кода, которые могут повредить клиентскую или серверную машины, крайне необходимы. Web была разработана как открытая система для публикации графического гипертекстового содержимого в Internet. Разработчики сайтов получили возможность расширять статические HTML-документы динамичес- динамическими, интерактивными возможностями за счет включе- включения в Web-документы языков создания сценариев. Язы- Языки создания сценариев могут выполняться на серверной машине или же загружаться на клиентскую машину и выполняться как удаленный код. Меры безопасности становятся крайне необходимыми, поскольку JavaScript и Java получают все большее распространение, стано- становясь таким образом более привлекательными целями для атак. Безопасность в подключенной к Internet компьютер- компьютерной сети может быть оценена в терминах уровня "кон- "конфиденциальности" передачи. Получающая сторона дол- должна быть уверена, что переданная информация была действительно послана указанным отправителем. Кро- Кроме того, сообщение не должно по пути изменяться. В гетерогенной компьютерной сети, коей является Internet, подобная конфиденциальность в настоящее время не может быть абсолютной. Internet задумывался и разра- разрабатывался как распределенная система, посредством которой поток информации в сети должен пройти че- через огромное количество различных машин, чтобы доб- добраться до указанного адресата. Проходя через множество хостов, трафик подвергается модификациям или заме- заменам множество раз. Адрес отправителя может быть вы- вымышленным (подставным). Хотя всеобщая доступность и электронная структура незащищенных передач суще- существенно затрудняет учет, однако шифрование, цифро- цифровые подписи и проверка исходного кода — все это от- относится к попыткам противостоять атакам. Пользователь должен быть уверен, что код приложе- приложения будет вести себя надлежащим образом и не разру-
avaScriptu безопасность в Web шит пользовательскую систему. В типичной настольной среде код, постоянно находящийся на локальном жес- жестком диске, считается заслуживающим доверия, в то время как код, полученный из сетевых ресурсов (уда- (удаленный код) может претендовать на гораздо более низ- низкий уровень доверия — в зависимости от источника (кор- (корпоративная сеть или сайт хакера вирусов). В прошлом доверие обычно зависело от происхождения кода при- приложения. Риск при установке пакета, купленного в роз- розничной продаже и произведенного известной фирмой, минимален по сравнению с риском при загрузке самой новой игры, свободно распространяемой в Internet. Ус- Установка электронных распределительных каналов для лриложений (JavaScript и кода Java) требует принятия новой технологии и процедур, а также обучения потен- потенциальных потребителей. Компьютерная промышленность движется к назна- назначению цифровых сигнатур разработчиков и к созданию подписанных аплетов, способных определять безопас- безопасность для JavaScript-кода. Идентификацией JavaScript- разработчика будет, вероятно, передача на Web-браузер цифровой сигнатуры, добавленной в конце файла сце- сценария. Пользователи, имеющие более новые браузеры, на основе полученной сигнатуры смогут решать, при- принимать ли загрузку кода с сайта. Рисунок 35.1 показы- показывает типичное диалоговое окно, отображающее инфор- информацию, которая содержится в цифровом сертификате. РИСУНОК 35.1. Типовой вид цифрового сертификата. Шифрование используется для предотвращения из- изменения передаваемых данных в пути. Слой безопас- безопасных сокетов (Secure Sockets Layer, SSL) и протокол безопасной передачи гипертекстов (Secure Hypertext Transport Protocol, SHTTP) гарантируют, что фрагмен- фрагменты JavaScript-кода в процессе передачи не изменялись. Наконец, проверка исходного кода — критичный фак- Глава 35 тор для обеспечения безопасной среды. Проверки на ви- вирусы расширены и устанавливают, что JavaScript-код не содержит никаких опасных подпрограмм. Стоимость и сложность мер безопасности, осуществ- осуществляемых для защиты компьютерной системы пользова- пользователя, должна учитывать затруднения, налагаемые их существованием. Ниже приводится список областей уязвимости машины клиента при выполнении кода сце- сценария: Изменение файловой системы •• Чтение/запись в файл • Чтение/запись системной памяти Отправка по сети приватной информации • Связь с другими сетевыми ресурсами Выполнение/завершение программ на локальном ком- компьютере или внешнем хосте Использование чрезмерных системных ресурсов (ата- (атаки типа "Отказа в обслуживании") • Авария программы хоста (Web-браузера) Языки программирования создавались, чтобы предо- предоставить разработчикам инструментальные средства для конструирования приложений. Для обеспечения мер безопасности, связанных с выполнением кода у сетевых клиентов, компания Netscape разработала JavaScript, не содержащий многие функции традиционных языков программирования. Отсутствие некоторых возможнос- возможностей обеспечивает в Web еще один уровень защиты от атак, однако препятствует созданию изящного содержи- содержимого приложения. В этой главе рассматриваются воз- возможности JavaScript- и Java-кода по нарушению безо- безопасности, а также шаги, которые можно предпринять в плане предотвращения атак подобного рода. Концепции безопасности в клиентской части JavaScript Наиболее распространенная в настоящее время опас- опасность на локальных машинах, имеющих доступ в Internet, связана с выполнением у клиента удаленного JavaScript- кода. Использование клиентского JavaScript допустимо при условии выяснения источника документа. Суще- Существование HTML-дескриптора <SCRIPT> указывает на то, что данная страница содержит клиентский код, а необязательный атрибут дескриптора LANGUAGE= "JAVASCRIPT" определяет, что страница содержит код на языке JavaScript. JavaScript-код может быть встроен в исходный HTML-документ либо находиться в отдельном фай- файле, на который ссылаются при помощи другого нео- необязательного атрибута дескриптора <SCRIPT> -
Избранные программные технологии Часть V SRC="javqfile.js"Если выполнение JavaScript в данном Web-браузере разрешено, сценарий может выполнить- выполниться немедленно после загрузки страницы и ее обработ- обработки с помощью интерпретатора сценариев или JIT- (Just- In-Time) транслятором. Некоторые браузеры содержат опцию предупреждения пользователя прежде, чем сце- сценарий начнет выполняться и предлагают пользователю возможность выделить определенные заслуживающие доверия сайты. С точки зрения традиционных программистов на- настольных систем в настоящее время безопасность при выполнении клиентского JavaScript обеспечивается драконовскими мерами. При выполнении в Netscape Navigator на JavaScript-код накладываются следующие ограничения: • Отсутствие возможности читать или записывать фай- файлы. Отсутствие доступа к информации файловой систе- системы. JavaScript не может выполнять программы и систем- системные команды. • JavaScript не может подключаться к другим компь- компьютерам, кроме той машины, из которой аплет был выгружен. • Ограничения доступа к данным <FORM>. JavaScript-приложения не могут сохранять пользо- пользовательскую информацию на локальном жестком диске, кроме как через механизм cookie-наборов, связь с под- подключаемым модулем и одной кодовой уловкой. Уловка основана на передаче информации вспомогательному приложению. Если пользователь указал вспомогательное приложение для MIME-типа, JavaScript-код может от- открыть окно сообщения и вывести информацию о вспо- вспомогательном приложении. Пользователь тогда сможет явно сохранить информацию на клиентской машине с помощью опции вспомогательного приложения File -» Save. На рис. 35.2 показано, что происходит после пе- передачи данных notepad.exe на примере кода test_stream. Следующий код описывает функции, необходимые для выполнения такой операции: function fcest_streamO ¦:< msgwindow = window.open("","hiwin",""); // или // text/sams для определения нового MIME-типа msgwindow.document.write("JavaScript data, save "to sick drive \nA, 100, 3S\nH); // вывести какой-то текст sgwindow.document.write("Choose File I Save to ^create a data file") ; msgwindow.document.close(); msgwindow. close () ; Saue info to disk 1Л.1oo.OICImose ftlelSjue to save data File РИСУНОК 35.2. Загрузка клиенту данных из JavaScript. ПРЕДОСТЕРЕЖЕНИЕ Если в document.open передается параметр (mime- type), определяемый как "Ask User" или "Save" в под- .меню "Helper", сценарий не сохранит информацию и сгенерирует ошибку Out of Memory. 'Поскольку document.write в настоящее время не мо- может записывать null (\0) в поток данных, в этом при- примере используются только двоичные файлы. Правильное понимание клиентских ограничений, которые могут затрагивать операции сценария, критич- критично для доступа кода сценария к информации о среде пользовательского браузера. Сценарий может произве- произвести запрос класса navigator, чтобы выяснить вид систем- системной платформы или версию и тип браузера. Подобным же образом можно получить список зарегистрирован- зарегистрированных MIME-типов и подключаемых модулей. Свойства navigator предназначены только для чтения и поэтому не требуют принятия дополнительных мер безопасно- безопасности. Системные свойства, которые могут быть получе- получены за счет доступа к классу navigator, сведены в табл.. 35.1. Таблица 35.1. Свойства класса navigator. Имя свойства Описание navigator.appCodeName navigator. appName navigator.appVersion navigator. mimeTypes[] navigator.plugins[] navigator.userAgent Кодовое имя браузера Приложение браузера Версия браузера Доступные MIME-i Установленные подключаемые модули Строка HTTP agent ПРИМЕЧАНИЕ Строка HTTP agent отправляется серверу в течение HTTP-запросов. Как Netscape Navigator, так и Microsoft Internet Explorer обеспечивают доступ к классу navigator. JavaScript не используется для создания приложений, ответственных за управление доступом. Поскольку пользо- пользователь может просматривать весь JavaScript-код в окне исходного документа (или фрейма), совершенно не- несложно вскрыть алгоритм защиты. Все файлы, загружен- загруженные с помощью необязательного дескриптора исходно-
avaScript и безопасность в Web го файла, доступны для пользовательской загрузки и шифрования. Атаки на службы Атаки на службы приносят наибольший ущерб, по- поскольку пользователь не может завершить выполняю- выполняющийся JavaScript-код. Атаки на службы могут заблоки- заблокировать пользовательский интерфейс и потребовать, чтобы пользователь завершил сеанс браузера. Наиболее частыми атаками являются: Переполнение стека Бесконечные циклы Бесконечные модальные диалоги Использование всей доступной памяти Переполнение стека Состояние переполнения стека — наиболее простая в плане предотвращения атака на службы, которую лег- легко перехватить всеми браузерами. В этом случае отобра- отображается окно ошибки JavaScript с сообщением "Out of Stack Space or Stack overflow in function_x" (см. рис. 35.3). Приведенный ниже код демонстрирует, как созда- создавать переполнение стека, многократно вызывая рекур- рекурсивную функцию: <НТМ1.ХНЕМ» <TITI,E> Create Recursive Function Call Condition</TITLE> ¦ Файл lockstack.htm --> <scr::pt> function stack_lockup(){ stack_lockup() ;) </SCRIPTX/HEADXBODY> Entering Recursive Function Call <SCRIPT LANGUAGE="JavaScript"> комментарий, который обеспечивает //невозможность отображения кода В браузерах, //не поддерживающих Javascript stack_lockup();//эта строка выполняется // немедленно после загрузки документа не // забывайте использовать HTML-комментарий —> </SCRIPTX/BODYX/HTML> РИСУНОК 35.3. Окн, ошибки Netscape 1 переполнении стека. при Глава 35 Бесконечные циклы Бесконечные циклы — головная боль для всех програм- программистов, и разработчикам JavaScript-кодов не избежать этой участи. Следующий кодовый фрагмент подвесит браузер: for(var i=O document.write("End this message"); ПРВДОСПРЕЖЕНЙЕ JavaScript-код, выполняющий бесконечные циклы, бло- блокирует все окна браузера, включая окно загрузки файлов. По утверждению Netscape, JavaScript-код дол- должен завершаться после выполнения 100000 проходов цикла, а пользователи должны иметь возможность на- нажать на кнопку "Stop". Однако, я НИ разу не замечал, чтобы браузеры выполняли второе условие. Бесконечные модальные диалоги JavaScript-код, многократно отображающий сигнальные окна, может служить примером атаки методом бесконеч- бесконечного модального диалогового окна. Следующий фраг- фрагмент кода подвесит пользовательский интерфейс брау- браузера: for(var i=0;;i++> alert("Why can't i kill this script"); Использованиевсей доступной памяти Netscape Navigator не ограничивает объем памяти, ко- которую может распределить JavaScript. В конце концов, эта атака переполняет виртуальную память и замедля- замедляет машину: for(var i=0;;i++) str = str + "why doesn't everyone play nice"; В большинстве своем такие атаки очевидны и мог- могли бы быть остановлены, если бы пользователь имел воз- возможность завершить выполнение сценария (особен- (особенность, в настоящее время исследуемая Netscape). Более изощренная атака основана на постепенном разрушении службы. Код-преступник на JavaScript не занимает ма- машину, а только накапливает ресурсы в одной точке так, что все другие окна браузера кажутся застывшими. Проблемы Netscape Navigator 2.0 ПРИМЕЧАНИЕ Поскольку Netscape 2.0 и Internet Explorer 3.0 в насто- настоящий момент не особенно популярны, многое из при- приведенной ниже информации устарело. Браузер Netscape Navigator 2.0 демонстрирует кон- консервативный подход к уравновешиванию потребностей разработчика с потребностями защиты пользователя путем введения мер безопасности. Так как большинство
Избранные программные технологии Часть V дыр в защите в более поздних версиях Netscape Navigator было устранено, корректный JavaScript-код, разработан- разработанный для версии 2.x, часто не выполняется должным образом в более поздних версиях. Баланс между приватным и общим доступом к JavaScript-информации в Navigator 2.0 был вполне ясен. Navigator автоматически предотвращал доступ сценария из одного сервера к свойствам документов, постоянно находящихся на другом сервере. Эти меры безопаснос- безопасности не допускали, чтобы сценарий выбирал приватную информацию, которую пользователь не хотел бы обна- обнародовать. Начиная с версии Navigator 2.0, появилась возможность низкоуровневой перезаписи кода, про- проблемного с точки зрения безопасности. Наиболее важ- важно здесь то, что правила, связанные с согласованием сценариев разных серверов, были ослаблены и оформ- оформлены в виде новой методологии — преднамеренного ис- искажения данных. Необходимо знать наиболее важные ошибки в вер- версии Netscape Navigator 2.x и модифицировать браузер, используя самые последние его обновления. Netscape исправил большинство ошибок в версиях 2.01 и 2.02. В основном, это касалось ликвидации дыр в защите, свя- связанных с выполнением Java. Было бы неплохо, чтобы пользователи и разработчики воспользовались как мож- можно более новыми версиями Netscape Navigator. Более поздние версии Navigator Основная модификация интерпретатора JavaScript из- изменила определение допустимого кода по сравнению с более ранними версиями. Меры безопасности для бра- браузеров Netscape постоянно изменяются с учетом разви- развития правильного равновесия между возможностями язы- языка и уровнем пользовательской секретности. Операция вызова document была изменена с целью обеспечения гарантии того, что JavaScript-код не будет записываться поверх исходного сценария. Наличие вы- вызовов функций document.open или document.write фун- функции вне дескрипторов <BODY>, не ссылающихся на новое окно, приводит к ошибке. Ниже приведен при- пример недопустимого сценария: <SCRIPT LANGUAGE="Javascript"> var i; function initialize_app() t i = "I"; function setup (> document.open(); document.write ("My test app equals",i); initialize_app(); document.close(); j </SCRIPT> <BODY onload="setup()"></BODY> В данном случае браузер создает новый контекст документа и тем самым сбрасывает старый JavaScript. В результате выводится сообщение об ошибке "initialize_app is not defined" (initialize_app не определе- определена), поскольку JavaScript-интерпретатор больше не име- имеет доступа к функции. Необходимыми для обеспечения безопасности действиями в данном случае будет либо запись всего текста после завершения функции onload, либо же запись нового документа в другой фрейм. Сле- Следующий пример демонстрирует первый из упомянутых вариантов: <SCRIPT> function setup О i initialize_app(); i </SCRIPT> <BODY onload="setup() "> </BODY> <SCRIPT> document.write("My test app equals",i); </SCRIPT> Преднамеренное искажение данных Концепция искажения данных была помещена в язык как механизм совместного использования данных для окон, открытых из различных серверов. Искажение дан- данных можно осуществить, устанавливая системную пе- переменную NS_ENABLE_TAINT в любое значение. Когда искажение данных разрешено, все JavaScript- объекты и свойства становятся общедоступными. Данная возможность необходима для совместного использования разными окнами информации от разных серверов. Окна могут получать "чужую" информацию от других доступ- доступных окон, но когда эта информация посылается на сер- сервер, всплывает диалог подтверждения, позволяющий отменить или подтвердить операцию post. Если систем- системная переменная не установлена, ссылки на данные форм на других серверах будут генерировать сообщения об ошибке "access disallowed from scripts at VRLl.himto documents at C/R/,2.htm"^ocTyn из сценария по URLl .htm в документы по URL2.htm запрещен). СОВЕТ <::iw Даже когда искажение данных заблокировано, окна имеют возможность обращаться к функциям, загру- загруженным в другие окна с других серверов. Например, framel, загруженный с serveri, может вызвать функ- функцию frame2, загруженную с server!. JavaScript предоставляет функции, позволяющие устанавливать или удалять искажение данных в объек- объектах. Функция taint() возвращает искаженную ссылку на свойство, a untaint() — ее неискаженную копию. Напри- Например, следующий код возвращает копию приватных дан- данных, которые можно отправить на сервер через URL либо операцию POST формы:
avaScriptu безопасность в Web unmarked = untaint(document.forms[0].element[0] .value) ; ПРЕДОСТЕРЕЖЕНИЕ Когда системная переменная NS_ENABLE_TAINT уста- новгена, JavaScript-код в одном из окон видит все свойства документов из других окон, включая приват- приватные данные и информацию списка посещений в тече- течение данного сеанса. Механизм искажения в настоящее время содержит много ошибок, связанных с безопасностью, и должен применяться весьма осторожно. Многие разработчики создавали код, обходящий механизм защиты за счет обновления данных через последовательность манипу- манипуляций с ними. .Internet Explorer 3.x Поскольку возможность выполнения JavaScript- и Java- аплетов только недавно была включена в Internet Explorer Microsoft, независимые эксперты еще не успели подго- подготовить широкий обзор его механизмов безопасности. Обзор интерфейса приложения показывает хорошо про- продуманный подход к безопасности. Меры обеспечения секретности и регистрация аплетов были встроены в браузер и работают с пользователем, гарантируя, что информация будет передаваться на сервер только явно. На рис. 35.4 показано диалоговое окно, содержащее все возможности по обеспечению секретности, доступные в Internet Explorer. Geneial ] Connection | Navigation | Programs Security (Advanced | Piivacy ^fc*>. Г }*/frn me betaejetidi" over an open Г Warrj me before crossing zdnst f7 Wan me .about invalid .site certificate? Г Warn mebetoi«etcepting"?ODkiet'* es Use certificates la positively identify sites, pubd'sheis am yourself. Penonal.. 1 . I Pubfchws. e conlcnt Kl ^*°° can c^loose ^at '^P® °f «ftwaeWeb sues can P dovvnload and run on your computer. P AHcw dowrfo&inQ of act/ve content Enable ActiveX corttots and plugim P RunActiveXscripIs P EnableJavapiogfarTB Safety Level. РИСУНОК 35.4. Возможности обеспечения безопасности в Microsoft Internet Explorer, Интерфейс приложения также включает возмож- возможность ограничения загрузки кода только серверами, зас- заслуживающими доверия. Эта особенность основывается на использовании сервером сертификатов безопасности Глава 35 для идентификации при просмотре сайтов, заслужива- заслуживающих доверия. Internet Explorer имеет диалоговое окно,, которое может отображать сайтыу которым доверяет клиентский браузера (см. рис. 35.5). Trusted Publbhef * and Issu You have d-ygn.ited the following ^oi M agencies as means initaB and use softwaie van these pufab these agencies without «kjng you first. ^^ I pJ3lJshers and с а can d by Г" Consider all ccmfneicial sottwate publishers ttrth РИСУНОК 35.5. Диалоговое окно Windows SoftwareSecurity, Максимизация надежности защиты Прежде чем отправляться в плаванье по неизведанным водам, можно предпринять шаги по уменьшению воз- воздействия атак на безопасность из-за "предательства" Java- или JavaScript-кода. Можно определить, какой уровень защиты необходимо задействовать, опираясь на объем доверия для данного источника. При посещении новых сайтов (либо уже просмотренных сайтов после запроса virus hackers) желательно полностью удалить возмож- возможность выполнения языков создания сценариев в браузе- браузере. Кроме того, сетевой администратор может выбрать нисходящий подход к безопасности, отключив выпол- выполнение Java-классов, полученных из Internet. Сетевая безопасность может конфигурироваться для удаления возможности передачи файлов Java-классов через про- прокси-сервер во внутреннюю сеть. Если отслеживаются сводки и советы по безопасности, должно быть хорошее представление о риске обхода сетевой защиты. Безопасные сеансы и цифровые сигнатуры Как упоминалось ранее, безопасные сеансы иницииру- инициируются браузером; при этом устанавливается шифрован- шифрованный поток передачи данных между сервером и браузером. Шифрование основывается на цифровых сертификатах, хранящихся на сервере. Дальнейшая защита достигает- достигается за счет использования цифровых подписей для каж- каждого файла, загруженного клиенту. Авторитетные службы проверки, такие как Verisign, трудятся бок о бок с раз- разработчиками браузеров с целью создания структуры для добавления цифровых сигнатур в файлы сценариев и аплетов. Более поздние версии Netscape Navigator и Internet Explorer, в дополнение к экранным визуальным
Избранные программные технологии Часть V подсказкам, обеспечивают информацию о текущем уровне безопасности документов или фреймов. Для просмотра уровня безопасности документа (или фрейма) в Netscape Navigator выберите View ' Page Info ("Document Info" в старых версиях) или View -* Frame Info. Строка Security дает текущий уровень безопасно- безопасности. На рис. 35.6 показана информации о безопасности в Netscape Navigator. Для просмотра уровня безопасности документа (или фрейма) в Microsoft Internet Explorer выберите File Properties, а затем — вкладку Security, либо щелкните на кнопке Certificates, в зависимости от используемой версии Internet Explorer. На рис. 35.7 показана инфор- информация о безопасности в Internet Explorer. NetA-t File MIME Type: Sour»: Local cacho rae: fctip^'totwonh tfjJicwft'' texUhtml MOOWJVH La.t Modified: Monday. 29-Ji&9< 17W IOL*c«ltk« Last Modified: CoivtenrlengUi: Expires Cbanetr Severity: Cattificm№ Monday. ?9-Jul-S»6 21 04;1fl dMT 3307 No date gWen ITas is a secure document that use: a rnednm-grade encryption key suited for TJ ^ezpul ffi.C4-Eaport. 128bitwiA40secreO. rU*C*rtife>hb*b4i « TO» Ccrtlflntonabnnlhr; mt*nithgiJtc3# Stein Зн-лгСмьАмЦоп Anthoiijr tJALTT«etnologi»i,![ie H3A DaU3*cuniy Inc PUUtnxeb. Ркшу^ш». US US Serial Nurohen 02:78 00:0* 9A Thii Certificate i»»afid freitk Мои .Ы 22,195* to Sun Jw» 26,1997 Certificate Fittfcatprinti РИСУНОК 35.6. Информационное окно Netscape Navigator, сообщающее о защищенности документа. Отключение языков создания сценариев в браузере На уровне индивидуального клиента наиболее эффек- эффективный способ защиты пользователя от повреждения кодовых фрагментов должен просто убирать возмож- возможность выполнения браузером кода создания сценария. Недостаток подобного подхода состоит в том, что тог- тогда из Web-сайта будут удалены многие возможности, поэтому Web-сайт не сможет работать, как задумыва- задумывалось. Эти параметры следует использовать только при посещении непроверенных сайтов. JavaScript Для отключения JavaScript в Netscape Navigator 2.01 выберите Options-» Security Preferences и вкладку General. Отметьте флажок Disable JavaScript (Запретить JavaScript) и затем щелкните на кнопке ОК. ПРИМЕЧАНИЕ В Netscape Navigator 2.0 отключить JavaScript нельзя. rfam4t№«bojtit! bdbK Ceililicate HamAm L-Pittsbugh O"GALT Technologies. Inc :N-netwoithgaK.cmi isuer 0-RSAOataSecuity, te. DUs S Cft Sarwturp Type E lie typt ion Type. Pifvacy Strength: Effective pata 7/23^3612;00:00 ДМ E Kpiration D ate: 1 /26/9? 11 ?333FW Security Pioiccol: SSL го nSA/MD5 RC4 Low D0 b*f( J РИСУНОК 35.7. Информационное диалоговое окно Internet Explorer, сообщающее о защищенности документа. Для отключения JavaScript в более поздних версиях Netscape Navigator выберите Edit ¦* Preferences (см. рис. 35.8) и выберите опцию Advanced. Удалите отметку на флажке Enable JavaScript (Разрешить JavaScript) и затем щелкните на кнопке ОК. ! f" i sitsi ижа: [IcH'-.i .Mi'.^4.1 e.tv :"гигк-.:,.., > ebss j r;v2i ¦ ¦ ¦ ¦ ¦ .r «.—r - ¦ ¦¦ .. ад,: ' Ai K0I №¦ Web ¦ РИСУНОК 35.8. Отключение JavaScript в более поздних версиях Netscape Navigator. Для отключения JavaScript в Internet Explorer 4 или более поздних версиях выберите Tools -» Internet Options и вкладку Security. Щелкните на кнопке Custom Level, отыщите Active Scripting (см. рис. 35.9) и выберите Disable. В Internet Explorer 3 отключить JavaScript нельзя. Java Для отключения JavaScript в Netscape Navigator 2.01 выберите Options -» Security Preferences и вкладку General. Отметьте флажок Disable Java и щелкните на кнопке ОК.
avaScriptu безопасность в Web Для отключения Java в более поздних версиях Netscape Navigator выберите Edit -* Preferences (см. рис. 35.8) и выберите опцию "Advanced". Снимите отметку флажка Enable Java и затем щелкните на ОК. Для отключения JavaScript в Internet Explorer выбе- выберите Tools -* Internet Options и вкладку Security. Щел- Щелкните на кнопке Custom Level, отыщите Java. Выбери- Выберите Disable, а затем щелкните на кнопке ОК. На рис. 35.10 показано диалоговое окно Internet Explorer, кото- которое используется для запрещения Java-программ. FireusmnJa' й:>,^ HlPtTW CD«t«tlMllV LUHoiau О Ем Nl_ J= РИСУНОК 35.9. Отключение JavaScript в Internet Explorer. РИСУНОК 35.10. Отключение Java в Internet Explorer. Фильтрация через брандмауэр Бранлмауэры (firewall) и прокси-серверы обычно пред- представляют собой первую линию защиты между Internet и внутренней сетью (WAN, LAN или удаленной маши- машиной). Сетевые администраторы могут конфигурировать маршрутизаторы брандмауэра с целью фильтрации се- сетевого потока данных, базируясь на различных парамет- Глава 35 pax, и таким образом гарантировать, что пользователь не сможет загрузить файл, вызывающий нарушение бе- безопасности. Однако, уровень фильтрации должен быть определен с учетом баланса выгод, достигаемых при более высоком уровне безопасности, и стоимости реа- реализации такого решения. Реализация решений по безо- безопасности для маршрутизатора или прокси-сервера вообще дорого обходится в плане затрат ресурсов и финансов, поэтому следует предварительно убедиться, что подоб- подобного рода защита действительно необходима. HTTP-запросы используются клиентским браузером для запрашивания фрагментов JavaScript и Java-кодов. Поскольку HTTP также используется для нормального функционирования Web-браузера, прокси-сервер не может запретить доступ ко всем HTTP-запросам, по- поскольку это бы привело к недоступности Web для браузе- браузера. Технология фильтрации (которая может использо- использоваться для удаления загрузки Java) должна фильтровать URL для блокировки всех файлов, имеющих расшире- расширение .class или .cla. Фильтрация JavaScript-кода более сложна, так как исходным файлам разрешено исполь- использовать любые расширения, а кодовые фрагменты могут быть внедрены во внутренние Web-страницы. Информационные ресурсы о безопасности для JavaScript и Java В Internet имеется множество сайтов, содержащих ин- информацию по проблемам безопасности. Сбор информа- информации об актуальных мерах безопасности — неплохое начало для принятия правильных решений о риске, возникающем при использовании последних техноло- технологий. Наиболее точная информация содержится на следу- следующих Web-сайтах: • Netscape:http://developer.netscape.com/docs/manuals/ index.html Информация, связанная с продукцией Netscape: Sun на http://java.javasoft.com/sfaq/ Информация, связанная с Java: CERT на http:// www.cert.org • Независимые консультации о текущих нарушениях безопасности: CERT FTP на ftp://info.cert.org/pub/ certadvisories • Поисковый каталог для файлов, содержащих слово Java: Safe Internet Programming на http:// www.cs.princeton.edu/sip/. Этот сайт создан исследо- исследовательской группой Принстонского университета, которая занимается расширением Internet-сценариев. Именно они обнаружили самые последние проколы в защите Java.
Избранные программные технологии Часть V Концепции безопасности в серверной части JavaScript Функциональные возможности Web-серверов можно расширить через выполнение подпрограмм JavaScript и Java, а также CGI-программ и серверных модулей. Сер- Серверное расширение JavaScript применяет существующие возможности языка JavaScript для создания приложе- приложений, которые могут обращаться к базам данных и другим ресурсам, постоянно находящимся на сервере. Возмож- Возможность выполнения серверного расширения JavaScript на сервере Netscape в настоящее время описана как техно- технология LiveWire и допускается через администратора сервера. На рис. 35.11 показано окно Enterprise Server, которое используется для активизации серверного рас- расширения JavaScript (LiveWire). Activate LiveYVirf n '.Linage?п n Jittn:Vrrt bi РИСУНОК 35.11. Активизация серверного расширения JavaScript. Важно знать, что возможности серверного расшире- расширения JavaScript должны отображаться на определенные каталоги на сервере. Потребность санкционирования каталогов сервера, выполняющих серверное расширение JavaScript, помогает защитить сервер, изолируя облас- области, которые могли бы вызвать нарушения безопаснос- безопасности. На рис. 35.12 показано окно сервера, используемое для активизации LiveWire для указанного подкаталога сервера. Технология LiveWire предоставляет четыре новых объекта JavaScript для применения на сервере: request, client, project и server. Объект request содержит свойство request.ip, которое позволяет серверу определять IP- адрес, от которого исходит клиентский запрос. Этот объект используется для проверки заслуживающих до- доверия клиентов, которым может быть предоставлен до- доступ к конфиденциальной информации. Объект гло- глобальных данных приложения project, должен быть заблокирован прежде, чем будут изменяться (еремен- ные значения данных, иначе целостность переменных и счетчиков приложения не будет синхронизирована между клиентскими процессами. ¦-•-- -¦¦•¦ РИСУНОК 3 5.12. Активизация катсыогов Live И in • для выполнения JavaScript. Наибольшего внимания требуют меры безопасности для возможностей серверного расширения JavaScript читать и записывать информацию непосредственно на жесткий диск. Определенным образом отформатирован- отформатированные данные могут часто разрушать программы, которые читают или записывают файлы. Код серверного сцена- сценария необходимо тщательно протестировать, дабы обре- обрести уверенность, что перед записью на диск данные пользователя переводятся в допустимый формат. Также обязательно, чтобы код серверного JavaScript содержал механизмы закрытия файлов, учитывая, что многие ;сы выполняются на главном сервере. Наиболее простой механизм блокировки предполагает переимено- переименование файла перед открытием его для файлового ввода- вывода. Во всех операционных системах команда rename, как и следовало ожидать, будет элементарной операцией. Следующий код иллюстрирует it прин- принцип: while (rename (,)) // лереиме ювать файл для // целей блокировки // заблокировать доступ к файлу else { // выполнить файловый ввод/вывод mame ( ,) ; // восстановить оригинальное / / имя файла } Серверный код не должен записывать файлы на диск в общедоступные каталоги, для которых установлена возможность запуска. Обычная хакерская уловка состоит
avaScriptu безопасность в Web в применении заслуживающей доверия серверной про- программы для создания файла на сервере, который позже может использоваться для атаки. Например, грамма, которая загружает текстовые файлы от клиен- клиента на сервер, может послужить для создания выполня- выполняемого файла сценария. Когда атакующий обращается к загруженному файлу через Web-браузер, серверный код выполняется и может натворить бед на сервере. Администраторы Web-сайтов и разработчики кода должны знать, что серверный JavaScript вполне может разрушить промышленный сервер. Чрезмерное исполь- использование системной памяти, некорректная блокировка объектов, бесконечные циклы и неверный файловый ввод-вывод может привести к аварийному останову сер- сервера. Весь код сценария должен быть полностью про- протестирован на сервере динамически перед запуском его в работу. Кроме того, код потребуется опытным путем проверить на возможные тупиковые ситуации. ПРВДОСгеРЕЖЁНИЕ Клиентское расширение JavaScript может попытаться обратится к любому порту на исходном сервере. По- Потребуется выполнить проверку безопасности, которая бы гарантировала, что между сервером и internet при- присутствует надлежащая сетевая защита. .: Интерпретатор Java необходимо явно активизировать для каталогов сервера. Управление приложениями сер- сервера используется для определения каталогов, которые могут выполнять Java-модули. На рис. 35.13 показана страница управления прило- приложением, используемая для активизации Java для опре- определенного подкаталога сервера. РИСУНОК 35.13. Активизация каталогов Java на сервере. Java и безопасность Язык Java предлагает намного больше возможностей, нежели JavaScript. Более поздние версии Netscape Глава 35 позволяют разработчику реализовать смешанные Java- и JavaScript-коды внутри Java-аплетов (технология LiveConnect). К тому же, JavaScript может напрямую обращаться к функциям Java-аплетов, передавая пара- параметры и получая возвращаемые значения. Эти два язы- языка могут использоваться в тандеме для создания исчер- исчерпывающих решений для удаленных клиентов. Знание истории Java важно в плане преодоления возможных проблем безопасности, связанных с его те- текущей реализацией. Язык копирует C++ во многих от- отношениях — он имеет тот же синтаксис, похожие клю- ключевые слова и поддержку объектно-ориентированной методологии, включая и наследование. Java отличается от C++ в том, что добавляет в язык гибкость и пытается создавать более безопасную среду: код не может подде- подделывать указатели, сборка мусора осуществляется авто- автоматически, реализуется только одиночное наследование. Машино-независимая структура Java изолирует програм- программиста от операционной системы целевой машины. Ос- Основные стандартные блоки программирования расши- расширены предварительно подготовленными пакетами,, способными определять систему клиента и сервера. Язык Java первоначально предназначался для созда- создания встроенных приложений на персональных прибо- приборах (настольные телевизоры, персональные коммуника- коммуникаторы, карманные компьютеры и т. п.). Возможность атак на эти закрытые системы намного ниже, чем при соеди- соединении с самой большой общедоступной сетью с откры- открытыми стандартами. Программный интерфейс приложения, предложен- предложенный Sun Microsystems для языка Java, в процессе обще- общественной стадии тестирования был достаточно устойчив, чтобы обрабатывать большинство задач, необходимых в традиционных настольных компьютерных приложе- приложениях. Цель состояла в том, чтобы разрешить заслужи- заслуживающему доверия браузеру или заслуживающей доверия Java-среде обрабатывать непроверенные компоненты Java-класса. Текущая реализация Java потеряла такое разрешение, так как его механизмы безопасности не соответствуют основным промышленным стандартам безопасности для заслуживающих доверия систем. Сам по себе язык Java не может считаться безопасным, по- поскольку не имеет самых базовых компонентов безопас- безопасной архитектуры. Java не содержит основных механизмов безопасно- безопасности, таких как возможность проверки в загрузчике клас- классов в документ модулей, загруженных в процессе ата- атаки. Поскольку аплеты могут существовать вне контекста Web-документа, который их загрузил, аплет-жулик мо- может проводить атаку без того, что пользователь заметит его существование. Определяемая пользователем поли- политика проверки должна быть доступна, что позволяет регистрировать выполнение аплета, сетевой адрес аплета и байт-код аплета.
Избранные программные технологии Часть V Добавим, что реализации Java не доказали, что он является безопасным языком, как предполагали его со- создатели. Большинство подсистем содержат ошибки за- защиты, которые не были полностью исправлены, что приводит к повторяющимся сигналам об ошибках защи- защиты. Таблица 35.2 подробно описывает наиболее важные из них, которые зарегистрированы Sun Microsystems на странице Applet Security FAQ (http://java.sun.com/sfaq/). Исследователи, которые обнаружили эти ошибки защиты, публично заявили, что Java придется радикаль- радикально изменить, чтобы достичь их определения безопасной среды. Атака с использованием незаконного приведения типа успешно обходит механизм безопасного приведе- приведения типа в Java. Успешные атаки на механизм приведе- приведения типа позволяют Java-объектам подменять свой тип. Разработка хакерами жульнического загрузчика класса означает, что непроверенный код приложения потенци- потенциально может быть загружен и выполнен из непроверен- непроверенного источника без ведома браузера. Компоненты защиты Механизмы защиты, управляющие Java-объектами, ре- реализованы на Java. При запуске рабочей системы брау- браузера не возникает никаких ограничений по защите. Класс SecuntyManager, контролирующий безопасность, загружается из каталога, содержащегося в клиентской системной переменной CLASSPATH. Такие заслужива- заслуживающие доверия файлы класса (MOZxxx.ZIP в Netscape Navigator 2.0 и JAVxxx.ZIP в Netscape Navigator 3.x) должны быть защищены частыми проверками на виру- вирусы и содержать пометку "только для чтения". Верификатор байт-кода Когда Java-класс выгружается из удаленного хоста, код проверяется верификатором байт-кода. Этот важный шаг гарантирует, что код Java соответствует известным кодам операций языка и что стек операндов не подвер- Таблица 35.2. Некоторые ошибки защиты Java. Дата гнут переполнению или потере значимости. Все досту- доступы к объектам класса проверяются на соблюдение ме- механизма защиты, определенного для членов объектов (приватный, защищенный, общедоступный). Кроме того, код проверяется на отсутствие каких-либо неза- незаконных преобразований данных. После того как вери- верификатор исполнит свою работу, код преобразовывает- преобразовывается рабочим Java-компилятором в машинный код. Управление защитой Класс SecurityManager используется рабочей системой Java для доступа к разрешению управления Java-клас- Java-классами. Поскольку SecurityManager реализован как Java- объект, когда начинается выполнение, управление бе- безопасностью защищается системой Java-типов. Если система типов доказала безопасность, и файловая сис- система не была поставлена под угрозу, SecurityManager считается заслуживающим доверия классом. Трансляторы Java отвечают за компиляцию исход- исходного Java-кода (файл с расширением Java) в машино- независимый байт-код (файл с расширением .class). Байт-код передается по сети на локальную машину и интерпретируется либо компилируется в первоначаль- первоначальный код системой выполнения Java. Проверка байт-кода Java является критическим шагом в определении цело- целостности Java-аплета. Таким же образом, как текущие программы проверки на вирусы ищут незаконные про- процессы и системные вызовы, байт-код проверяется на отсутствие каких-либо атак на безопасность. Байт-коды должны оцениваться в контексте их типов. Например, тип SecurityManager должен иметь меньшее количество ограничений по сравнению с типом, определяемым пользователем. Недостаток формального определения для системы типов Java и необходимость полного анализа всей ра- рабочей последовательности программы приводит к тому, что оценка выполняется текущими верификаторами, сложными и ненадежными. Проблема Состояние 26 марта 1999 г. Непроверенный код 22 июля 1998 г. Принстонская атака загрузчика класса 2 июля 1996 г. Атака с применением незаконного приведения типа 18 мая 1996 г. Новая версия предыдущей атаки загрузчика класса Апрель 1996 г. Атака разрешения имени URL Март 1996 г. Ошибка выполнения верификатора Март 1996 г. Ошибка выполнения загрузчика класса Февраль 1996 г. Атака DNS Исправлена в JDK 1.1.8 Исправлена в JDK 1.2 Исправлена в JDK 1.1 Исправлена в Netscape 3.0Ь4 Исправлена в Netscape З.ОЬ4 Исправлена в Netscape 2.02 Исправлена в Netscape 2.01 Исправлена в Netscape 2.01
avaScript и безопасность в Web Методы защиты аплетов предписывается концепци- концепцией пространства имен (named space). Каждый Java-аплет должен иметь уникальное имя, в зависимости от источ- источника, из которого он был загружен. Документация Java утверждает, что пространство имен объектов системного' уровня имеет возможность совместного использования всеми другими пространствами имен (аплетами), и что загрузчик класса во время выполнения всегда ишет спи- список системных пространств имен, дабы уберечь загру- загруженный код от перезаписи системного класса. Стоит добавить, что подделка пространств имен хеша, кото- которые заменяют жизненно важные системные компонен- компоненты класса, такие как загрузчик класса, было одной из первых ошибок защиты, найденных в Java. Ошибки заг- загрузчика класса были подробно задокументированы ис- исследователями Принстонского университета. Ограничения защиты Базовое подмножество языка Java было расширено за счет многих важных пакетов классов, которые уберега- уберегают программистов от повторного изобретения основных интерфейсов. Реализация пакета может освободить про- программиста от связанных с платформой проблем, но так- также может ограничить доступ к некоторым компонентам нижнего уровня. Определенная реализация Java оказы- оказывает влияние на базовый доступ к машинным подсис- подсистемам, ответственным за сетевую связь, файловому вво- вводу-выводу, доступу к памяти и системным ресурсам. В настоящее время серверный Java-код имеет меньшее количество ограничений защиты по сравнению с кли- клиентским Java-кодом. СОВЕТ . ; iB Java-коде сообщения об ошибках, включающие тер- термин Security Except ion, указывают на нарушение огра- ограничений защиты. Сетевая связь Использование концепции совместной работы Sandbox "песочницы"служит для ограничения возможностей свя- связи для кода аплета с другими машинами. Подобного рода аплет может связываться только с сервером, из которо- которого он исходит. Ограничение кода "игрой только в своей песочнице" — первая линия защиты от жульнического аплета. Менеджер безопасности ограничивает сетевые вызовы так, что они могут только открывать каналы связи между клиентом и исходным DNS-адресом апле- аплета. Поскольку в вопросе проверки адреса методология полагается на DNS-подсистему, компромиссы сервера DNS, з свою очередь, сводят на нет эффективность механизма безопасности. Согласно документации, аплеты могут открывать каналы связи с сервером через любой порт. В действи- |5 1-158 Глава 35 тельности, выполнение Java в Netscape устанавливает недокументированные ограничения, определяющее до- доступность разных портов. Наличие аплета в наборе инструментов, который де- делает запрос всех сокет-портов и возвращает возмож- возможные каналы связи, экономит достаточно много времени при определении портов, поддерживаемых конкретной реализацией Java. Файловый ввод-вывод Текущие реализации клиентских расширений Java не разрешают чтение и запись на жесткий диск клиента. На клиентской машине вызовы для открытия, чтения, за- записи и закрытия файлов генерируют уведомление SecurityExceptions или IOExceptions. Приложение Applet Viewer от Sun Microsystems использует файл управления доступом, чтобы предоставить чтение и разрешение за- записи на диск клиента. Вероятно, что некоторые опера- операции из этой схемы будут в будущем приняты новым браузером Netscape. Как упоминалось ранее в главе, серверное расширение Java может обращаться к жест- жесткому диску хоста для выполнения операций с файлами. Доступ в память В Java исходный код не имеет концепции указателей памяти. Это существенно упрощает использование язы- языка и уменьшает количество ошибок кода. Поскольку указателями не ссылаются на структуры данных, мно- много сторонников Java полагают, что он должен быть бо- более безопасным языком по сравнению с C++. К тому же, программисты Java не могут подделывать указате- указатели на функции. Системные ресурсы Возможность блокирования системных ресурсов явля- является риском безопасности в Java. Например, в реализа- реализации Netscape блокирование класса java.net.InetAddress приводит к блокированию всех новых сетевых подклю- подключений. Как Java, так и JavaScript — революционные языки, которые помогают разработчикам Web-сайтов создавать, интерактивное содержимое. Однако, возможность запус- запуска удаленного кода на клиентских машинах должна рас- рассматриваться и с точки зрения потенциального нанесе- нанесения ущерба среде пользователя. Цель сообщества поставщиков программного обеспе- обеспечения под Internet заключается в создании заслужива- заслуживающей доверия среды, в которой пользователей не дол- должно волновать, что действия могут повлечь за собой разрушительные последствия. В идеале пользователь также должен знать, что операция собирается произой- произойти, и иметь возможность предотвратить это.
Избранные программные технологии Часть V Механизмы все еще развиваются с целью создания более безопасной подключенной к сети среды, интуи- интуитивно понятной пользователю. Меры безопасности, ин- инкапсулированные в JavaScript-код, еще не готовы к ис- использованию в критических средах, однако быстрый рост Internet-технологий приближает реализацию реше- решений. Резюме Поскольку компьютерные пользователи выходят за рам- рамки настольных систем и связываются с деловыми парт- партнерами и друзьями по всему миру, проблемы, связан- связанные с компьютерной безопасностью и секретностью становятся проблемами первостепенной важности. В главе рассматривались клиентские области, которые должны быть защищены от преднамеренных атак, и было показано, как пользователи могут уберечь свои машины при выполнении программ на JavaScript и Java. Методологии безопасности пребывают в настоящее вре- время в состоянии разработки. Запуск удаленного кода на клиентских машинах в текущих реализациях строго ог- ограничен, так как потребности пользователя и разработ- разработчика сбалансированы мерами, направленными против потенциально некорректного употребления. Знание ог- ограничений и особенностей текущей технологии критич- критично при установке требуемого уровня доверия и распро- распространении динамических и изящных приложений и содержимого в Internet.
Приложение ЧАСТЬ в этой части А. Десять основных ресурсов в Web, посвященных JavaScript •• f
Десять основных ресурсов в Web, посвященных JavaScript Netscape DevEdge Online http://developer.netscape.com Это центральный Web-сайт компании Netscape для всех его технологий разработки. Здесь можно найти офици- официальную документацию Netscape no JavaScript, а также статьи и информационные бюллетени, отражающие все, что Netscape делает в мире JavaScript. Сайт включает следующие страницы: • JavaScript Authoring Guide по адресу http:// developer.netscape.com/docs/manuals/communicator/ jsguide4/index. htm • JavaScript Developer Central по адресу http:// developer.netscape.com/tech/javascript/index.html • Official JavaScript Language Specification по адресу ftp://ftp.netscape.com/pub/review/jsspec.ps.gz ; Технологии написания сценариев Microsoft http://msdn.microsoft.com/scripting/default.htm Это главный Web-сайт компании Microsoft, содержащий информацию по JScript и VBScript. Здесь можно выгрузить самую новую версию сценарного механизма Microsoft, а также найти документацию и примеры применения JScript и VBScript. Сайт включает следующие страницы: JScript Language Reference по адресу http:// msdn.microsoft.com/scripting/jscript/doc/jstoc.htm JScript FAQ по адресу http://msdn.microsoft.com/ scripting/jscript/techinfo/jsfaq.htm JScript Samples по адресу http://msdn.microsoft.com/ scripting/jscript/samples/jssamp.htni Введение в JavaScript от Voodoo http://rummelplatz.uni-mannheim.de/~skoch/js/ script.htm Введение в JavaScript от Voodoo — обучающая программа в 12 частях, охватывающая все популярные аспекты JavaScript. Она пригодна как для новичков, так и для экспертов. Часть 1 объясняет, что такое JavaScript и как он используется, а следующие части рассматривают применения слоев и динамического HTML. llrt.org http://www.irt.org/articles/script.htm Irt.org (Internet Related Technologies) содержит огромное количество высококачественных статей по всем раз- разделам, включая ASP, HTML, динамический HTML, VBScript, CSS, XML, JavaScript и т.д. Приведенный выше URL определяет непосредственно раздел JavaScript, где можно отыскать множество полезных статей в удоб- удобно организованном каталоге. Focus on JavaScript http://javascript.about.com Этот сайт поддерживается Нейтом Кассебаумом (Nate Kassebaum), одним из соавторов этой книги. Здесь мож- можно найти еженедельные статьи, посвященные JavaScript, а также ссылки на последнюю информацию на других сайтах. Сайт содержит следующие страницы: About.com JavaScript Tutorial по адресу http:// javascript.about.com/library/bl_tutorial.htm Focus on JavaScript Newsletter по адресу http:// javascript.about.com/gi/pages/mmail.htm
JavaScriptu Worldwide Web SuperScripter http://www.builder.com/Programming/Scripter/ Это раздел, посвященный JavaScript, на Builder.com в. C|NET. Каждую неделю JavaScript-гуру Builder.com пишет статью, рассматривающую какой-либо аспект JavaScript. Архив содержит лучшие статьи и примеры, доступные в Web. JavaScripts.com http://www.javascripts.com JavaScripts.com содержит тысячи готовых примеров JavaScript-кода для использования при создании Web- страниц. Сайт предназначен только для членов, однако членство на нем свободное и все, что требуется — это указать свой адрес электронной почты. JavaScript Source http://javascript.internet.com JavaScript Source является прежде всего библиотекой примеров кода JavaScript, но он также содержит форум Приложение А и раздел по книгам, посвященным JavaScript. Библио- Библиотека кодов очень хороша и содержит свыше 500 высо- высококачественных сценариев. Webcoder.com http://www.Webcoder.com Webcoder.com содержит примеры сценариев, статьи с практическими рекомендациями, ссылки на JavaScript и динамический HTML, а также демонстрационные страницы для многих популярных и новых JavaScript- приложений. Website Abstraction http://www.wsabstract.com Website Abstraction — большой каталог свободно доступ- доступных JavaScript-кодов и обучающих программ JavaScript. Сайт также содержит информацию и примеры других Web-технологий, таких как Java и динамический HTML.
Сопровождающий CD-ROM Сопровождающий CD-ROM содержит много полез- полезных инструментальных средств и утилит, плюс исход- исходные коды и примеры, рассмотренные в книге. Установка на компьютерах Macintosh 1. Вставьте CD-ROM в дисковод. 2. Когда пиктограмма CD-ROM появится на рабочем столе, откройте CD-ROM, дважды щелкнув на его пиктограмме. 3. Дважды щелкните на пиктограмме Guide на CD-ROM и следуйте выводимым инструкциям. Установка под управлением Windows 98 1. Вставьте CD-ROM в дисковод. 2. Дважды щелкните на пиктограмме My Computer (Мой компьютер) на рабочем столе. 3. Дважды щелкните на пиктограмме, представляющей дисковод CD-ROM. 4. Дважды щелкните на пиктограмме SETUP.EXE для запуска программы установки. 5. Программа установки создает программную группу с именем "JavaScript Unleashed 3", содержащую пик- пиктограммы, которые можно использовать для про- просмотра CD-ROM. - примечание;1!"¦"" '"'" ¦ ¦ '^ЙЖ * * *'* ' ' Если на компьютере установлена Windows 98 и раз- разрешена возможность AutoPlay (Автозапуск), программа SETUP.EXE будет автоматически запускаться после помещения CD-ROM дисковод. Установка под управлением Windows NT 1. Вставьте CD-ROM в дисковод. 2. Выберите File -> Run (Файл -* Запуск) в провод- проводнике. 3. Введите drive:\SETUP.EXEk нажмите Enter (drive соответствует имени дисковода CD-ROM). 4. Программа установки создает программную груп- группу с именем "JavaScript Unleashed 3", которая содер- содержит пиктограммы, используемые для просмотра CD-ROM.
Предметный указатель Символы Opera 28, 44 I 74 '0Рега З'х 19 * 404 Sun's HotJava 3.0 28 * He-JavaScript 47, 49 * /b старые 39 && 74 (...) 403 B * 403 Ввод пользовательский 210 + 73 403 Верификация данных 367, 373 --> 33, 66 Визуальные эффекты 277 4оз Внедрение сценариев 55 I зз Внешние файлы 303 // 39 Выделение текста (onSelect) 193 < зз Вызов Java-методов 335 <!-- 33 66 Выражение 64 «76' Выход из документа (onUnload) 197 = gi Выход из фокуса (onBlur) 192 == 50 72 Вычисляемые поля 377 > 33 ' 1Г »76 Генерация событий >» 77 программная 198 ? 403 Графический пользовательский [...] 403 интерфейс (GUI) 103 ["•¦¦] 403 д } Декремент 70 76' 403 Денежные значения 379 76'403 Дескриптор I" 74 <applet> 20, 24, 330 A <BASE> 254 Агрегирование 106 <ЫУ> 33 Т^ 20'ofa. <*> ?99,312 Аргумент 93, 94 <form> 319 Архитектура клиент/сервер 163 <FRAME> 242 255 Атрибут 34, 104 <FRAMESET> 242 Class 34 <head> 33 Id 34 <hr> 33 Name 34 <html> 33 Style 34 <iframe> 293, 299, 303 Атрибуты DOM 186 <ilayer> 33, 293, 305 R <layer> 33, 293, 305 <link> 287 Баннер 277, 278 <marquee> 33 Бегущая строка 277 <meta> 36 Библиотека <noscript> 47 классов 106 <object> 330 объектов 106 <script> 29, 34, 46, 55 Блок данных 299 <span> 289 Браузер 18, 28, 39, 44, 47 <style> 287 Be'sNetPositive2.1 28 <table> 312 HotJava 44 <td> 33 Microsoft Internet Explorer 18, 44 закрывающий 33 Navigator 200 контейнерный 33 NCSA Mosaic 21 одиночный 33 NetF'osffive 44 открывающий 33 Netscaoe Naviaator 18. 44 пустой 33 Диалоговое окно Prompt 49 Диалоговые окна 208 Динамическая инструментальная панель 360 Динамическая подмена (rollover) 272 Динамический HTML (DHTML) 311 Документ HTML 167 Доступ к Java из JavaScript 330 Доступ к JavaScript из Java 331 Дочерний (child) элемент 286 3 Загрузка документа (onLoad) 196 Замена обработчиков событий 198 Запрос 164, 412 HTTP 165 клиентский 164 поисковый 412 Запуск приложения 414 Зарезервированное слово 58 Захват данных с помощью объекта Textarea 231 И .Идентификатор 57 Изменение данных (onChange) 191 Изоморфизм 186 Инициализация переменных 428 Инкапсуляция 106 Инкремент 70 Инсталляция приложений 170 Инструментальные панели 317 Интерфейс 164, 411 поисковый пользовательский 411 пользовательский 164 Источник данных 409 К Карта изображения 252 Кеширование файлов 252 Класс 106, 107 Ключевое слово 58 Код 48 помещение во внешний файл 48 Кодирование URL 166 Командные кнопки 277, 282 анимированные 277 Комментарии 66, 286 Компания 16, 53 Apple 17 Borland 17 Digital 17 Informix 17 Oracle 17 Microsoft 17 Netscape 16, 53
JavaScript. Энциклопедия пользователя Sun 16, 53 Sun Misrosystems 24 Sybase 17 Константа 63 Конструктор 108, 151 RegExp() 401, 405 Косвенная установка фокуса 207 Кредитные карточки 380 Л Лексема 57 Литерал 58 логический 59 с плавающей точкой 58 строковый 59 целочисленный 58 Логическое или (|) 403 М Массив 141, 151 Меню 311 Метка 89 Метод Alert() 208, 423 CloneNode 268 Close() 204 Confirm!) 210 ConfirmOrder() 190 ConvertToUppercase() 191 DailyTaskf) 199 Focusf) 191 llnsertBefore 269 Open() 189, 201 Prompt 49 Prompt)) 210 RemoveNode 269 SelectContentsf) 192 Setlnterval 198 SetTmneoutO 199, 277 SwapNode 269 Writef) 215, 251 Writelnf) 215 итератор 111 конструктор 111 модификатор 111 общедоступный 106 приватный 106 Методы DOM 184 CloneNodef) 184 RemoveNodeQ 184 Модель 29, 186 объектная 29 структурная 186 Н Навигация между окнами 200, 207 то документу 186, 187 по сайту 360 по списку посещений 262 Наследование (inheritance) 286 Обработка ошибок (опЕггог) 188, 197, 420 Обработчик событий 50, 198 Onload 50 Замена 198 Обработчик событий (event handler) 50, 188, 198 onAbort 198 onBlur 192 onChange 191 onClick 189 onError 197 onFocus 191 onLoad 196 onMouseQut 193 onMouseOver 193 onReset 190 onSelect 193 onSubmit 190 onUnload 197 Объект Anchor 122, 214, 223 Applet 122 Area 122 Array 141 BLOB 180 Boolean 148 Button 126, 225, 231, 361 Checkbox 126, 225, 233 Client 173 Connection 179 Cursor 179 Database 178 Date 144 DbPool 178 Document 119, 182, 214 File 175 FileUpload 126 Form 122, 182, 225 Frame 120, 182, 200, 242 Function 149 Global 131 Hidden 126, 225, 239 History 120, 200, 242, 360, 365 Image 123, 214, 223 Layer 124 Link 125, 214, 218 Location 121, 200, 242, 262 Lock 175 Math 147 Mimetype 115 Navigator 114, 200, 242, 264 Number 149 Option 130 Password 126, 225, 238 Plugin 115, 125 Project 173 Radio 126, 225, 234 RegExp 141 Request 174 Reset 128 Resultset 180 Select 128, 225, 235 SendMail 177 Server 172 Stproc 180 String 131 Text 129, 225, 229 Textarea 129, 231 Toolbar 361 Window 116, 182, 200 простой 156 составн 157 Объектная модель 29 Объектная модель документа (DOM) 182, 266 Объявление переменных 428 Окно Upgrade Notice 196 браузера 201 закрытие 204 косвенная установка фокуса 207 навигация между окнами 207 определение атрибутов окна 202 открытие и закрытие 201 ссылки на окна 202 Оператор 40, 50, 82 Document.write() 40 lf..else 50 Switch 91 With 90 организации цикла 85 Break 88 Continue 88 Do..while 88 For 85 Fon.in 87 While 88 условный 82: If 82 If..else 84 Try..catch 85 присваивания 401 Операции 60, 69, 70 арифметические 70 булевы 74 декремента 70 инкремента 70 конкатенации 73 поразрядные 75 поразрядные логические 76 поразрядные сдвига 76 приоритеты выполнения 79 присваивания 70 со структурами данных 75 сравнения 711 строковые 73 условные 74 Определение слоев 312 Открытие нового URL 260 Отладка 170 Отношение "целое-часть" 106 Отношения содержания 110 Отправка формы (onSubmit) 190
Предметный указатель Ошибки 171, 353, 420 времени выполнения 421 логические 421 синтаксические 420 сообщения об ошибках 421 П Панели инструментов DHTML 311 Передача по значению 95 Переключатель 126 Переменная экземпляра 108 Переменные 60, 93 глобальные 62 локальные 62 область действия 62 Перемещение мыши по объектам 193 Лерсонапизация 386 Подключаемые модули 25, 54 Java 330 браузера 326 Подпрограмма 30 Получение фокуса (onFocus) 191 Пользовательский ввод 210 Поля вычисляемые 377 Помещение кода во внешний файл 48 Преобразование строк и чисел 140 ParseRoatf) 140 Parsaint() 140 Прерывание загрузки изображения (onAbort) 198 Приложение 22 клиентское 22, 27 Программирование модульное 318 Программная генерация событий 198 Протокол TCP/IP 25 Р Регулярные выражения 401 Рекурсия 101 Родительский (parent) элемент 286 С Сайт 47 Сброс формы (onReset) 190 Свойства 19, 104, 151, 251 объекта 111 Location.href 251 Селектор 289 смешивание 289 Сервер 25, 164 Apache 25 Microsoft Internet Information Server (IIS) 25 Netscape Enyerprise Server (NES) 25 Синтаксис 57 Синхронизация фреймов 247 Слои 293, 312 Событие 56, 113, 272 blur 192 click 56, 189 focus 191 load 196 mouseOut 193 mouseover 56, 193 onFocus 191 onMouseDown 272 onMouseOver 272 onMouseUp 272 select 193 submit 190 unload 197 таймера 188, 198 Создание изображений 318 Сокрытие информации 107 Сообщение 107 Сообщения об ошибках 421 Состояние 104 Специальные символы 59, 139 Среда 20 Microsoft Active Server Pages 20 Netscape Enterprise Server 20 Ссылки 250 на окна 202 на фреймы 254 Стандарт 285 MIME 326 ЕСМА 17 Стили 286 Страницы динамические 386 статические 386 Строка 104, 131,379 преобразование 140 форматирование 135 запроса 398 Структурная модель 186 Структурный изоморфизм 186 Сценарий внедрение 55 Т Таблица 410 поиска 410 стилей 285 Каскадная 285 Текст 33 Текстовый редактор 42 BBEdit 43 TextPad 43 Тестирование кода 423 Технология перетаскивания (drag-and-drop) 43 Тип 61 MIME 326 браузера 356 данных 64 Boolean 64 Function 64 Number 64 Object 64 String 64 Точечная нотация (.) 109, 403 Трансляция типов данных 334 У Уведомление простое 208 Управление сеансами 165 событиями 188 Условный оператор 82 If 82 If. .else 84 Try. .catch 85 Установка Java-свойств 335 Ф Файл 36, 48, 54, 166 .js 36, 48, 168 Acrobat 54 Cookie 166 HTML 167 VRML 54 аудио- 54 библиотечный 168 видео- 54 Флажок 126 Форма 122, 367, 400 скрытая переменная 400 создание интерактивных форм 376 Фрейм 120, 201, 242 вложенный 245 обновлени 249 синхронизация фреймов 247 Функция ChangeState() 302 CheckBrowserO 302 DailyTask() 199 JSMarqueef) 277 OnLoad 38 Opendoc() 38 Process() 322 Repaintf) 279 RolllmageO 320 TakeBrowser() 3211 TheHref() 250 вызов 75 определение 75 передача по значению 95 рекурсивная 101 замены 406 очистки 406 поиска 406 ц Цвет 63, 281 постепенное изменение 281 документа 216 Целые числа 378 Ш Шаблон 49 Э Экземпляр 20, 108, 153
JavaScript. Энциклопедия пользователя Элемент дочерний (child) 286 Элементы управления ActiveX 24, 27, 326, 328 Эффект 299 мультипликационный 299 Я Язык сценариев 16 Язык программирования 53 AppletScript 53 С/О 53 Perl 53 Visual Basic 53 Иностранные термины А Active Server Pages (ASP) 17, 26, 163 ActiveX 20, 24, 328 Apache 25 Apple 17 AppletScript 53 Application Manager 170, 171 Application programming interfaces - API 26, 183, 312 IB Be's NetPositive 2.1 28 Borland 17 Borland IntraBuilder 45 С C/C+ 53 CGI - Common Gateway Interface 16, 20, 26, 53 CGI-программа 53 CGI-сценарий 16, 21 Client-side imagemaps, CSIM 252 cookie-набор 165, 386, 387 CSS 285 CSS positioning, CSS-P 285 CSS-свойства 295 Bottom 295 Height 295 Left 295 Right 295 Top 295 Visibility 298 Z-index 296 D DHTML 183, 184, 311 Digital 17 DLL 26 DOM 182, 266 -браузер 266 -документ 266 -метод 266 -модель 266 Е ЕСМА (European Computer Manufacturer's Association) 17 ECMAScript 17, 46 G GUI 103 H HP 17 HTML 16, 17, 29, 32, 183 встроенный 29 HTML 4 19 HTML-документ 21, 32, 55, 167 активный 22 динамический 21 HTML-код 318 HTML-комментарий 33 HTML-редактор 43 Allaire HomeSite 43 FrontPage 44 WYSIWYG 44 визуальный 43 текстовый 43 HTML-страница 20 HTTP-запрос 165 1 IBM 17 IDE 42 IIS 44 Informix 17 Interface Definition Language - IDL 183 Internet Explorer 3.0 17 Internet Requests For Comment (RFC) 326 IP-адрес 166 ISAPI 26 J Java 16, 20, 26, 54 Java Server Pages (JSP) 26,163 Java-аплеты 20, 27, 326, 330 JavaScript 16, 28, 53 JavaScript от Netscape 342 JScript 17 JScript от Microsoft 348 L UveAudio 326, 336 UveScript 16, 53 LreWire 163 M Microsoft Active Server Pages 20 Microsoft Internet Explorer 17, 18, 44 Microsoft Internet Explorer 3.x 19 Microsoft Internet Information Server (IIS) 25 MIME 25 N NCSA Mosaic 21 Netscape 16, 53, 252 подключаемые модули 24 Netscape Enterprise Server 20 ¦Netscape Enyerprise Server (NES) 25 Netscape Navigator 18, 28, 44 Netscape Navigator 2.x 19 Netscape Navigator 3.0 17 Netscape SSJS (Server-Side JavaScript) 26 NSAPI 26 ID Object Management Group - OMG 183 OCX 24 OOP - object-oriented programming 19 Opera 28 Opera 3.x 19 Oracle 17 P Perl 53 R RGB 217 Rollover-эффект 273, 320 S Server-Side JavaScript (SSJS) 17,45, 169 Slide Show 364 SSJS 26, 163, 166 Sun 16, 53 Sun Misrosystems 24 Sun's HotJava 3.0 28 Sybase 17 T TCP/IP 25 U URL 166 V VBScript 17, 25, 28, 29 подпрограмма 30 программирование 30 тип данных Variant 29 типы данных 29 функция 30 Visual Basic 17, 28, 53 Visual Basic for Applications 28 W W3C 32 Web 22 Web-браузер 44 Web-мастер 16 Web-приложение 22, 163 Web-сервер 20, 25 Web-страница 53, 386 Window Script Host (WSH) 20 World Wide Web 21 X XHTML 18, 32 XML 32, 183
УДК 004.43@31) ББК 32.973.26-018.1 В 14 ВАЙКАллен та шш. В14 JavaScript. Перекл.з англ./Аллен Вайк.—К.: ТОВ"ТВД" ДС", 2001.—480 с. Енциклопед1я користувача ISBN 966-7992-00-04 Книга JavaScript. ЕнциклопеЫя користувача являеться найбшьш повним учбовим та довщниковим KepiB- ництвом по yciM версшм мови JavaScript, у тому числ1 JavaScript 1.5 i JScript 5.0. На сьогодшшнш день JavaScri pt e найбшьш розповсюджена мова для написания сценарпв, яю забезпечують гадтримку штерактив- ного BMicTyWeb-CTOpiHOK. В книз! анал1зуеться широкий спектр питань, починаючи з основ мови 1закшчую- чи складними питаниями практичного використання технологш Web-дизайну. Докладно розглядаються: взаемод!я JavaScript та HTML; типи даних, операци, вирази i оператори; основи об'ектно-ор1ентовано1 мето- методологи та и реал1защя в JavaScript; об'екти 3i сторони юпента та сервера; DHTML; технолопя написания стшкого та надшного коду; методика В1дладки коду. Особлива увага придшяеться питаниям досягнення без- пеки Web-програм. У книз1 е багато практичиих прикладов, ЯК1 вщповщають специф1чним особливостям розробки \УеЬ-сайт1в з використанням JavaScript. Довщник по базовим мовним об'ектам робить з книги справжне настшьне кер1вництво. CD-ROM, який надходить разом з книгою, М1стить коди ycix проанал!зованихприклад1в, а також багато 1ншо1 корисно? 1нформацн. JavaScript. ЕнциклопеЫя користувача розрахована на широку аудиторпо розробникш програмного забезпе- чення для Web.
Аллен Вайк и др. JAVASCRIPT. ЭНЦИКЛОПЕДИЯ ПОЛЬЗОВАТЕЛЯ торгэдо«издательский дом DiaSoft Киев • Москва • Санкт-Петербург 2001